~ubuntu-branches/ubuntu/trusty/miro/trusty

« back to all changes in this revision

Viewing changes to portable/libtorrent/src/session_impl.cpp

  • Committer: Daniel Hahler
  • Date: 2010-04-13 18:51:35 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: ubuntu-launchpad@thequod.de-20100413185135-xi24v1diqg8w406x
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
Copyright (c) 2006, Arvid Norberg, Magnus Jonsson
4
 
All rights reserved.
5
 
 
6
 
Redistribution and use in source and binary forms, with or without
7
 
modification, are permitted provided that the following conditions
8
 
are met:
9
 
 
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.
18
 
 
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.
30
 
 
31
 
*/
32
 
 
33
 
#include "libtorrent/pch.hpp"
34
 
 
35
 
#include <ctime>
36
 
#include <iostream>
37
 
#include <fstream>
38
 
#include <iomanip>
39
 
#include <iterator>
40
 
#include <algorithm>
41
 
#include <set>
42
 
#include <cctype>
43
 
#include <algorithm>
44
 
 
45
 
#ifdef _MSC_VER
46
 
#pragma warning(push, 1)
47
 
#endif
48
 
 
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>
55
 
 
56
 
#ifdef _MSC_VER
57
 
#pragma warning(pop)
58
 
#endif
59
 
 
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"
82
 
 
83
 
#ifndef TORRENT_WINDOWS
84
 
#include <sys/resource.h>
85
 
#endif
86
 
 
87
 
#ifndef TORRENT_DISABLE_ENCRYPTION
88
 
 
89
 
#include <openssl/crypto.h>
90
 
 
91
 
namespace
92
 
{
93
 
        // openssl requires this to clean up internal
94
 
        // structures it allocates
95
 
        struct openssl_cleanup
96
 
        {
97
 
                ~openssl_cleanup() { CRYPTO_cleanup_all_ex_data(); }
98
 
        } openssl_global_destructor;
99
 
}
100
 
 
101
 
#endif
102
 
#ifdef TORRENT_WINDOWS
103
 
// for ERROR_SEM_TIMEOUT
104
 
#include <winerror.h>
105
 
#endif
106
 
 
107
 
using boost::shared_ptr;
108
 
using boost::weak_ptr;
109
 
using boost::bind;
110
 
using libtorrent::aux::session_impl;
111
 
 
112
 
namespace libtorrent {
113
 
 
114
 
namespace fs = boost::filesystem;
115
 
 
116
 
namespace detail
117
 
{
118
 
 
119
 
        std::string generate_auth_string(std::string const& user
120
 
                , std::string const& passwd)
121
 
        {
122
 
                if (user.empty()) return std::string();
123
 
                return user + ":" + passwd;
124
 
        }
125
 
        
126
 
 
127
 
}
128
 
namespace aux {
129
 
 
130
 
        struct seed_random_generator
131
 
        {
132
 
                seed_random_generator()
133
 
                {
134
 
                        std::srand(total_microseconds(time_now() - min_time()));
135
 
                }
136
 
        };
137
 
 
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
144
 
#endif
145
 
                )
146
 
                : 
147
 
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
148
 
                m_send_buffers(send_buffer_size),
149
 
#endif
150
 
                  m_files(40)
151
 
                , m_io_service()
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)
157
 
#else
158
 
                , m_upload_channel(m_io_service, peer_connection::upload_channel)
159
 
#endif
160
 
                , m_tracker_manager(m_settings, m_tracker_proxy)
161
 
                , m_listen_port_retries(listen_port_range.second - listen_port_range.first)
162
 
                , m_abort(false)
163
 
                , m_paused(false)
164
 
                , m_max_uploads(8)
165
 
                , m_allowed_upload_slots(8)
166
 
                , m_max_connections(200)
167
 
                , m_num_unchoked(0)
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)
179
 
                        , m_half_open)
180
 
#endif
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
184
 
                , m_logpath(logpath)
185
 
#endif
186
 
#ifndef TORRENT_DISABLE_GEO_IP
187
 
                , m_asnum_db(0)
188
 
                , m_country_db(0)
189
 
#endif
190
 
                , m_total_failed_bytes(0)
191
 
                , m_total_redundant_bytes(0)
192
 
        {
193
 
                error_code ec;
194
 
                m_listen_interface = tcp::endpoint(address::from_string(listen_interface, ec), listen_port_range.first);
195
 
                TORRENT_ASSERT(!ec);
196
 
 
197
 
                m_tcp_mapping[0] = -1;
198
 
                m_tcp_mapping[1] = -1;
199
 
                m_udp_mapping[0] = -1;
200
 
                m_udp_mapping[1] = -1;
201
 
#ifdef WIN32
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)
206
 
                {
207
 
                        // on vista the limit is 5 (in home edition)
208
 
                        m_half_open.limit(4);
209
 
                }
210
 
                else
211
 
                {
212
 
                        // on XP SP2 it's 10    
213
 
                        m_half_open.limit(8);
214
 
                }
215
 
#endif
216
 
 
217
 
                m_bandwidth_manager[peer_connection::download_channel] = &m_download_channel;
218
 
                m_bandwidth_manager[peer_connection::upload_channel] = &m_upload_channel;
219
 
 
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";
223
 
 
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";
233
 
#endif
234
 
 
235
 
#ifdef TORRENT_STATS
236
 
                m_stats_logger.open("session_stats.log", std::ios::trunc);
237
 
                m_stats_logger <<
238
 
                        "1. second\n"
239
 
                        "2. upload rate\n"
240
 
                        "3. download rate\n"
241
 
                        "4. downloading torrents\n"
242
 
                        "5. seeding torrents\n"
243
 
                        "6. peers\n"
244
 
                        "7. connecting peers\n"
245
 
                        "8. disk block buffers\n"
246
 
                        "\n";
247
 
                m_buffer_usage_logger.open("buffer_stats.log", std::ios::trunc);
248
 
                m_second_counter = 0;
249
 
                m_buffer_allocations = 0;
250
 
#endif
251
 
 
252
 
                // ---- generate a peer id ----
253
 
                static seed_random_generator seeder;
254
 
 
255
 
                m_key = rand() + (rand() << 15) + (rand() << 30);
256
 
                std::string print = cl_fprint.to_string();
257
 
                TORRENT_ASSERT(print.length() <= 20);
258
 
 
259
 
                // the client's fingerprint
260
 
                std::copy(
261
 
                        print.begin()
262
 
                        , print.begin() + print.length()
263
 
                        , m_peer_id.begin());
264
 
 
265
 
                // http-accepted characters:
266
 
                // excluding ', since some buggy trackers don't support that
267
 
                static char const printable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
268
 
                        "abcdefghijklmnopqrstuvwxyz-_.!~*()";
269
 
 
270
 
                // the random number
271
 
                for (unsigned char* i = m_peer_id.begin() + print.length();
272
 
                        i != m_peer_id.end(); ++i)
273
 
                {
274
 
                        *i = printable[rand() % (sizeof(printable)-1)];
275
 
                }
276
 
 
277
 
                m_timer.expires_from_now(seconds(1), ec);
278
 
                m_timer.async_wait(
279
 
                        bind(&session_impl::second_tick, this, _1));
280
 
 
281
 
                m_thread.reset(new boost::thread(boost::ref(*this)));
282
 
        }
283
 
 
284
 
#ifndef TORRENT_DISABLE_GEO_IP
285
 
        namespace
286
 
        {
287
 
                struct free_ptr
288
 
                {
289
 
                        void* ptr_;
290
 
                        free_ptr(void* p): ptr_(p) {}
291
 
                        ~free_ptr() { free(ptr_); }
292
 
                };
293
 
        }
294
 
 
295
 
        char const* session_impl::country_for_ip(address const& a)
296
 
        {
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());
299
 
        }
300
 
 
301
 
        int session_impl::as_for_ip(address const& a)
302
 
        {
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;
306
 
                free_ptr p(name);
307
 
                // GeoIP returns the name as AS??? where ? is the AS-number
308
 
                return atoi(name + 2);
309
 
        }
310
 
 
311
 
        std::string session_impl::as_name_for_ip(address const& a)
312
 
        {
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();
316
 
                free_ptr p(name);
317
 
                char* tmp = std::strchr(name, ' ');
318
 
                if (tmp == 0) return std::string();
319
 
                return tmp + 1;
320
 
        }
321
 
 
322
 
        std::pair<const int, int>* session_impl::lookup_as(int as)
323
 
        {
324
 
                std::map<int, int>::iterator i = m_as_peak.lower_bound(as);
325
 
 
326
 
                if (i == m_as_peak.end() || i->first != as)
327
 
                {
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));
330
 
                }
331
 
                return &(*i);
332
 
        }
333
 
 
334
 
        bool session_impl::load_asnum_db(char const* file)
335
 
        {
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);
339
 
                return m_asnum_db;
340
 
        }
341
 
 
342
 
        bool session_impl::load_country_db(char const* file)
343
 
        {
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);
347
 
                return m_country_db;
348
 
        }
349
 
 
350
 
#endif
351
 
 
352
 
        void session_impl::load_state(entry const& ses_state)
353
 
        {
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)
359
 
                {
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)
363
 
                        {
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();
368
 
                        }
369
 
                }
370
 
#endif
371
 
        }
372
 
 
373
 
        entry session_impl::state() const
374
 
        {
375
 
                mutex_t::scoped_lock l(m_mutex);
376
 
                entry ret;
377
 
#ifndef TORRENT_DISABLE_GEO_IP
378
 
                entry::dictionary_type& as_map = ret["AS map"].dict();
379
 
                char buf[10];
380
 
                for (std::map<int, int>::const_iterator i = m_as_peak.begin()
381
 
                        , end(m_as_peak.end()); i != end; ++i)
382
 
                {
383
 
                        if (i->second == 0) continue;
384
 
                        sprintf(buf, "%05d", i->first);
385
 
                        as_map[buf] = i->second;
386
 
                }
387
 
#endif
388
 
                return ret;
389
 
        }
390
 
 
391
 
#ifndef TORRENT_DISABLE_EXTENSIONS
392
 
        void session_impl::add_extension(
393
 
                boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
394
 
        {
395
 
                TORRENT_ASSERT(ext);
396
 
 
397
 
                typedef boost::shared_ptr<torrent_plugin>(*function_t)(torrent*, void*);
398
 
                function_t const* f = ext.target<function_t>();
399
 
 
400
 
                if (f)
401
 
                {
402
 
                        for (extension_list_t::iterator i = m_extensions.begin(); i != m_extensions.end(); ++i)
403
 
                                if (function_equal(*i, *f)) return;
404
 
                }
405
 
 
406
 
                m_extensions.push_back(ext);
407
 
        }
408
 
#endif
409
 
 
410
 
#ifndef TORRENT_DISABLE_DHT
411
 
        void session_impl::add_dht_node(udp::endpoint n)
412
 
        {
413
 
                if (m_dht) m_dht->add_node(n);
414
 
        }
415
 
#endif
416
 
 
417
 
        void session_impl::pause()
418
 
        {
419
 
                mutex_t::scoped_lock l(m_mutex);
420
 
                if (m_paused) return;
421
 
                m_paused = true;
422
 
                for (torrent_map::iterator i = m_torrents.begin()
423
 
                        , end(m_torrents.end()); i != end; ++i)
424
 
                {
425
 
                        torrent& t = *i->second;
426
 
                        if (!t.is_torrent_paused()) t.do_pause();
427
 
                }
428
 
        }
429
 
 
430
 
        void session_impl::resume()
431
 
        {
432
 
                mutex_t::scoped_lock l(m_mutex);
433
 
                if (!m_paused) return;
434
 
                m_paused = false;
435
 
                for (torrent_map::iterator i = m_torrents.begin()
436
 
                        , end(m_torrents.end()); i != end; ++i)
437
 
                {
438
 
                        torrent& t = *i->second;
439
 
                        t.do_resume();
440
 
                }
441
 
        }
442
 
        
443
 
        void session_impl::abort()
444
 
        {
445
 
                mutex_t::scoped_lock l(m_mutex);
446
 
                if (m_abort) return;
447
 
#if defined(TORRENT_LOGGING)
448
 
                (*m_logger) << time_now_string() << " *** ABORT CALLED ***\n";
449
 
#endif
450
 
                // abort the main thread
451
 
                m_abort = true;
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();
459
 
#endif
460
 
                error_code ec;
461
 
                m_timer.cancel(ec);
462
 
 
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)
466
 
                {
467
 
                        i->sock->close(ec);
468
 
                }
469
 
 
470
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
471
 
                (*m_logger) << time_now_string() << " aborting all torrents (" << m_torrents.size() << ")\n";
472
 
#endif
473
 
                // abort all torrents
474
 
                for (torrent_map::iterator i = m_torrents.begin()
475
 
                        , end(m_torrents.end()); i != end; ++i)
476
 
                {
477
 
                        i->second->abort();
478
 
                }
479
 
 
480
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
481
 
                (*m_logger) << time_now_string() << " aborting all tracker requests\n";
482
 
#endif
483
 
                m_tracker_manager.abort_all_requests();
484
 
 
485
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
486
 
                (*m_logger) << time_now_string() << " sending event=stopped to trackers\n";
487
 
                int counter = 0;
488
 
#endif
489
 
                for (torrent_map::iterator i = m_torrents.begin();
490
 
                        i != m_torrents.end(); ++i)
491
 
                {
492
 
                        torrent& t = *i->second;
493
 
                        t.abort();
494
 
                }
495
 
 
496
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
497
 
                (*m_logger) << time_now_string() << " sent " << counter << " tracker stop requests\n";
498
 
#endif
499
 
 
500
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
501
 
                (*m_logger) << time_now_string() << " aborting all connections (" << m_connections.size() << ")\n";
502
 
#endif
503
 
                m_half_open.close();
504
 
 
505
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
506
 
                (*m_logger) << time_now_string() << " connection queue: " << m_half_open.size() << "\n";
507
 
#endif
508
 
 
509
 
                // abort all connections
510
 
                while (!m_connections.empty())
511
 
                {
512
 
#ifdef TORRENT_DEBUG
513
 
                        int conn = m_connections.size();
514
 
#endif
515
 
                        (*m_connections.begin())->disconnect("stopping torrent");
516
 
                        TORRENT_ASSERT(conn == int(m_connections.size()) + 1);
517
 
                }
518
 
 
519
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
520
 
                (*m_logger) << time_now_string() << " connection queue: " << m_half_open.size() << "\n";
521
 
#endif
522
 
                TORRENT_ASSERT(m_half_open.size() == 0);
523
 
 
524
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
525
 
                (*m_logger) << time_now_string() << " shutting down connection queue\n";
526
 
#endif
527
 
 
528
 
                m_download_channel.close();
529
 
                m_upload_channel.close();
530
 
        }
531
 
 
532
 
        void session_impl::set_port_filter(port_filter const& f)
533
 
        {
534
 
                mutex_t::scoped_lock l(m_mutex);
535
 
                m_port_filter = f;
536
 
                // TODO: recalculate all connect candidates for all torrents
537
 
        }
538
 
 
539
 
        void session_impl::set_ip_filter(ip_filter const& f)
540
 
        {
541
 
                mutex_t::scoped_lock l(m_mutex);
542
 
 
543
 
                INVARIANT_CHECK;
544
 
 
545
 
                m_ip_filter = f;
546
 
 
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();
552
 
        }
553
 
 
554
 
        ip_filter const& session_impl::get_ip_filter() const
555
 
        {
556
 
                mutex_t::scoped_lock l(m_mutex);
557
 
                return m_ip_filter;
558
 
        }
559
 
        
560
 
        void session_impl::set_settings(session_settings const& s)
561
 
        {
562
 
                mutex_t::scoped_lock l(m_mutex);
563
 
 
564
 
                INVARIANT_CHECK;
565
 
 
566
 
                TORRENT_ASSERT(s.file_pool_size > 0);
567
 
 
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;
581
 
                m_settings = s;
582
 
                if (m_settings.connection_speed <= 0) m_settings.connection_speed = 200;
583
 
 
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())
590
 
                        *i = ' ';
591
 
        }
592
 
 
593
 
        tcp::endpoint session_impl::get_ipv6_interface() const
594
 
        {
595
 
                return m_ipv6_interface;
596
 
        }
597
 
 
598
 
        tcp::endpoint session_impl::get_ipv4_interface() const
599
 
        {
600
 
                return m_ipv4_interface;
601
 
        }
602
 
 
603
 
        session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
604
 
                , int retries, bool v6_only)
605
 
        {
606
 
                error_code ec;
607
 
                listen_socket_t s;
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())
612
 
                {
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);
617
 
#endif
618
 
                }
619
 
                s.sock->bind(ep, ec);
620
 
                while (ec && retries > 0)
621
 
                {
622
 
                        ec = error_code();
623
 
                        TORRENT_ASSERT(!ec);
624
 
                        --retries;
625
 
                        ep.port(ep.port() + 1);
626
 
                        s.sock->bind(ep, ec);
627
 
                }
628
 
                if (ec)
629
 
                {
630
 
                        // instead of giving up, try
631
 
                        // let the OS pick a port
632
 
                        ep.port(0);
633
 
                        ec = error_code();
634
 
                        s.sock->bind(ep, ec);
635
 
                }
636
 
                if (ec)
637
 
                {
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";
646
 
#endif
647
 
                        return listen_socket_t();
648
 
                }
649
 
                s.external_port = s.sock->local_endpoint(ec).port();
650
 
                s.sock->listen(5, ec);
651
 
                if (ec)
652
 
                {
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";
660
 
#endif
661
 
                        return listen_socket_t();
662
 
                }
663
 
 
664
 
                if (m_alerts.should_post<listen_succeeded_alert>())
665
 
                        m_alerts.post_alert(listen_succeeded_alert(ep));
666
 
 
667
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
668
 
                (*m_logger) << "listening on: " << ep
669
 
                        << " external port: " << s.external_port << "\n";
670
 
#endif
671
 
                return s;
672
 
        }
673
 
        
674
 
        void session_impl::open_listen_port()
675
 
        {
676
 
                // close the open listen sockets
677
 
                m_listen_sockets.clear();
678
 
                m_incoming_connection = false;
679
 
 
680
 
                m_ipv6_interface = tcp::endpoint();
681
 
                m_ipv4_interface = tcp::endpoint();
682
 
 
683
 
                if (is_any(m_listen_interface.address()))
684
 
                {
685
 
                        // this means we should open two listen sockets
686
 
                        // one for IPv4 and one for IPv6
687
 
                
688
 
                        listen_socket_t s = setup_listener(
689
 
                                tcp::endpoint(address_v4::any(), m_listen_interface.port())
690
 
                                , m_listen_port_retries);
691
 
 
692
 
                        if (s.sock)
693
 
                        {
694
 
                                m_listen_sockets.push_back(s);
695
 
                                async_accept(s.sock);
696
 
                        }
697
 
 
698
 
                        // only try to open the IPv6 port if IPv6 is installed
699
 
                        if (supports_ipv6())
700
 
                        {
701
 
                                s = setup_listener(
702
 
                                        tcp::endpoint(address_v6::any(), m_listen_interface.port())
703
 
                                        , m_listen_port_retries, true);
704
 
 
705
 
                                if (s.sock)
706
 
                                {
707
 
                                        m_listen_sockets.push_back(s);
708
 
                                        async_accept(s.sock);
709
 
                                }
710
 
                        }
711
 
 
712
 
                        // set our main IPv4 and IPv6 interfaces
713
 
                        // used to send to the tracker
714
 
                        error_code ec;
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)
718
 
                        {
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());
724
 
                        }
725
 
                }
726
 
                else
727
 
                {
728
 
                        // we should only open a single listen socket, that
729
 
                        // binds to the given interface
730
 
 
731
 
                        listen_socket_t s = setup_listener(
732
 
                                m_listen_interface, m_listen_port_retries);
733
 
 
734
 
                        if (s.sock)
735
 
                        {
736
 
                                m_listen_sockets.push_back(s);
737
 
                                async_accept(s.sock);
738
 
 
739
 
                                if (m_listen_interface.address().is_v6())
740
 
                                        m_ipv6_interface = m_listen_interface;
741
 
                                else
742
 
                                        m_ipv4_interface = m_listen_interface;
743
 
                        }
744
 
                }
745
 
 
746
 
                if (!m_listen_sockets.empty())
747
 
                {
748
 
                        error_code ec;
749
 
                        tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
750
 
                        if (!ec)
751
 
                        {
752
 
                                if (m_natpmp.get())
753
 
                                {
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());
757
 
                                }
758
 
                                if (m_upnp.get())
759
 
                                {
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());
763
 
                                }
764
 
                        }
765
 
                }
766
 
 
767
 
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
768
 
                m_logger = create_log("main_session", listen_port(), false);
769
 
#endif
770
 
        }
771
 
 
772
 
#ifndef TORRENT_DISABLE_DHT
773
 
 
774
 
        void session_impl::on_receive_udp(error_code const& e
775
 
                , udp::endpoint const& ep, char const* buf, int len)
776
 
        {
777
 
                if (e)
778
 
                {
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);
783
 
 
784
 
                        if (m_alerts.should_post<udp_error_alert>())
785
 
                                m_alerts.post_alert(udp_error_alert(ep, e));
786
 
                        return;
787
 
                }
788
 
 
789
 
                if (len > 20 && *buf == 'd' && m_dht)
790
 
                {
791
 
                        // this is probably a dht message
792
 
                        m_dht->on_receive(ep, buf, len);
793
 
                }
794
 
        }
795
 
 
796
 
#endif
797
 
        
798
 
        void session_impl::async_accept(boost::shared_ptr<socket_acceptor> const& listener)
799
 
        {
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));
805
 
        }
806
 
 
807
 
        void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
808
 
                , weak_ptr<socket_acceptor> listen_socket, error_code const& e)
809
 
        {
810
 
                boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
811
 
                if (!listener) return;
812
 
                
813
 
                if (e == asio::error::operation_aborted) return;
814
 
 
815
 
                mutex_t::scoped_lock l(m_mutex);
816
 
                if (m_abort) return;
817
 
 
818
 
                error_code ec;
819
 
                if (e)
820
 
                {
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";
826
 
#endif
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)
831
 
                        {
832
 
                                async_accept(listener);
833
 
                                return;
834
 
                        }
835
 
#endif
836
 
#ifdef TORRENT_BSD
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)
840
 
                        {
841
 
                                async_accept(listener);
842
 
                                return;
843
 
                        }
844
 
#endif
845
 
                        if (m_alerts.should_post<listen_failed_alert>())
846
 
                                m_alerts.post_alert(listen_failed_alert(ep, e));
847
 
                        return;
848
 
                }
849
 
                async_accept(listener);
850
 
 
851
 
                // we got a connection request!
852
 
                tcp::endpoint endp = s->remote_endpoint(ec);
853
 
 
854
 
                if (ec)
855
 
                {
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";
859
 
#endif
860
 
                        return;
861
 
                }
862
 
 
863
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
864
 
                (*m_logger) << time_now_string() << " <== INCOMING CONNECTION " << endp << "\n";
865
 
#endif
866
 
 
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;
873
 
 
874
 
                if (m_ip_filter.access(endp.address()) & ip_filter::blocked)
875
 
                {
876
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
877
 
                        (*m_logger) << "filtered blocked ip\n";
878
 
#endif
879
 
                        if (m_alerts.should_post<peer_blocked_alert>())
880
 
                                m_alerts.post_alert(peer_blocked_alert(endp.address()));
881
 
                        return;
882
 
                }
883
 
 
884
 
                // don't allow more connections than the max setting
885
 
                if (num_connections() >= max_connections())
886
 
                {
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";
891
 
#endif
892
 
                        return;
893
 
                }
894
 
 
895
 
                // check if we have any active torrents
896
 
                // if we don't reject the connection
897
 
                if (m_torrents.empty())
898
 
                {
899
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
900
 
                        (*m_logger) << " There are no torrents, disconnect\n";
901
 
#endif
902
 
                        return;
903
 
                }
904
 
 
905
 
                bool has_active_torrent = false;
906
 
                for (torrent_map::iterator i = m_torrents.begin()
907
 
                                , end(m_torrents.end()); i != end; ++i)
908
 
                {
909
 
                        if (!i->second->is_paused())
910
 
                        {
911
 
                                has_active_torrent = true;
912
 
                                break;
913
 
                        }
914
 
                }
915
 
                if (!has_active_torrent)
916
 
                {
917
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
918
 
                        (*m_logger) << " There are no _active_ torrents, disconnect\n";
919
 
#endif
920
 
                        return;
921
 
                }
922
 
 
923
 
                boost::intrusive_ptr<peer_connection> c(
924
 
                        new bt_peer_connection(*this, s, endp, 0));
925
 
#ifdef TORRENT_DEBUG
926
 
                c->m_in_constructor = false;
927
 
#endif
928
 
 
929
 
                if (!c->is_disconnecting())
930
 
                {
931
 
                        m_connections.insert(c);
932
 
                        c->start();
933
 
                }
934
 
        }
935
 
        void session_impl::close_connection(peer_connection const* p
936
 
                , char const* message)
937
 
        {
938
 
                mutex_t::scoped_lock l(m_mutex);
939
 
 
940
 
// too expensive
941
 
//              INVARIANT_CHECK;
942
 
 
943
 
#ifdef TORRENT_DEBUG
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));
947
 
#endif
948
 
 
949
 
#if defined(TORRENT_LOGGING)
950
 
                (*m_logger) << time_now_string() << " CLOSING CONNECTION "
951
 
                        << p->remote() << " : " << message << "\n";
952
 
#endif
953
 
 
954
 
                TORRENT_ASSERT(p->is_disconnecting());
955
 
 
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);
963
 
        }
964
 
 
965
 
        void session_impl::set_peer_id(peer_id const& id)
966
 
        {
967
 
                mutex_t::scoped_lock l(m_mutex);
968
 
                m_peer_id = id;
969
 
        }
970
 
 
971
 
        void session_impl::set_key(int key)
972
 
        {
973
 
                mutex_t::scoped_lock l(m_mutex);
974
 
                m_key = key;
975
 
        }
976
 
 
977
 
        void session_impl::unchoke_peer(peer_connection& c)
978
 
        {
979
 
                torrent* t = c.associated_torrent().lock().get();
980
 
                TORRENT_ASSERT(t);
981
 
                if (t->unchoke_peer(c))
982
 
                        ++m_num_unchoked;
983
 
        }
984
 
 
985
 
        int session_impl::next_port()
986
 
        {
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;
990
 
        
991
 
                int port = m_next_port;
992
 
                ++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";
997
 
#endif
998
 
                return port;
999
 
        }
1000
 
 
1001
 
        void session_impl::second_tick(error_code const& e)
1002
 
        {
1003
 
                session_impl::mutex_t::scoped_lock l(m_mutex);
1004
 
 
1005
 
// too expensive
1006
 
//              INVARIANT_CHECK;
1007
 
 
1008
 
                if (m_abort) return;
1009
 
 
1010
 
                if (e)
1011
 
                {
1012
 
#if defined TORRENT_LOGGING
1013
 
                        (*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
1014
 
#endif
1015
 
                        ::abort();
1016
 
                        return;
1017
 
                }
1018
 
 
1019
 
                float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f;
1020
 
                m_last_tick = time_now();
1021
 
 
1022
 
                error_code ec;
1023
 
                m_timer.expires_from_now(seconds(1), ec);
1024
 
                m_timer.async_wait(
1025
 
                        bind(&session_impl::second_tick, this, _1));
1026
 
 
1027
 
#ifdef TORRENT_STATS
1028
 
                ++m_second_counter;
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)
1033
 
                {
1034
 
                        if (i->second->is_seed())
1035
 
                                ++seeding_torrents;
1036
 
                        else
1037
 
                                ++downloading_torrents;
1038
 
                }
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)
1043
 
                {
1044
 
                        if ((*i)->is_connecting())
1045
 
                                ++num_half_open;
1046
 
                        else
1047
 
                                ++num_complete_connections;
1048
 
                }
1049
 
                
1050
 
                m_stats_logger
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"
1059
 
                        << std::endl;
1060
 
#endif
1061
 
 
1062
 
                // --------------------------------------------------------------
1063
 
                // check for incoming connections that might have timed out
1064
 
                // --------------------------------------------------------------
1065
 
 
1066
 
                for (connection_map::iterator i = m_connections.begin();
1067
 
                        i != m_connections.end();)
1068
 
                {
1069
 
                        peer_connection* p = (*i).get();
1070
 
                        ++i;
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");
1076
 
                }
1077
 
 
1078
 
                // --------------------------------------------------------------
1079
 
                // second_tick every torrent
1080
 
                // --------------------------------------------------------------
1081
 
 
1082
 
                int congested_torrents = 0;
1083
 
                int uncongested_torrents = 0;
1084
 
 
1085
 
                // count the number of seeding torrents vs. downloading
1086
 
                // torrents we are running
1087
 
                int num_seeds = 0;
1088
 
                int num_downloads = 0;
1089
 
 
1090
 
                // count the number of peers of downloading torrents
1091
 
                int num_downloads_peers = 0;
1092
 
 
1093
 
                torrent_map::iterator least_recently_scraped = m_torrents.begin();
1094
 
                int num_paused_auto_managed = 0;
1095
 
 
1096
 
                int num_checking = 0;
1097
 
                int num_queued = 0;
1098
 
                for (torrent_map::iterator i = m_torrents.begin();
1099
 
                        i != m_torrents.end();)
1100
 
                {
1101
 
                        torrent& t = *i->second;
1102
 
                        TORRENT_ASSERT(!t.is_aborted());
1103
 
                        if (t.bandwidth_queue_size(peer_connection::upload_channel))
1104
 
                                ++congested_torrents;
1105
 
                        else
1106
 
                                ++uncongested_torrents;
1107
 
 
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())
1111
 
                        {
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())
1116
 
                                {
1117
 
                                        least_recently_scraped = i;
1118
 
                                }
1119
 
                        }
1120
 
 
1121
 
                        if (t.is_finished())
1122
 
                        {
1123
 
                                ++num_seeds;
1124
 
                        }
1125
 
                        else
1126
 
                        {
1127
 
                                ++num_downloads;
1128
 
                                num_downloads_peers += t.num_peers();
1129
 
                        }
1130
 
 
1131
 
                        t.second_tick(m_stat, tick_interval);
1132
 
                        ++i;
1133
 
                }
1134
 
 
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)
1141
 
                {
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())
1147
 
                        {
1148
 
                                (*i)->start_checking();
1149
 
                        }
1150
 
                }
1151
 
 
1152
 
                if (m_settings.rate_limit_ip_overhead)
1153
 
                {
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());
1157
 
                }
1158
 
 
1159
 
                m_stat.second_tick(tick_interval);
1160
 
 
1161
 
                // --------------------------------------------------------------
1162
 
                // scrape paused torrents that are auto managed
1163
 
                // --------------------------------------------------------------
1164
 
                if (!is_paused())
1165
 
                {
1166
 
                        --m_auto_scrape_time_scaler;
1167
 
                        if (m_auto_scrape_time_scaler <= 0)
1168
 
                        {
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;
1173
 
 
1174
 
                                if (least_recently_scraped != m_torrents.end())
1175
 
                                {
1176
 
                                        least_recently_scraped->second->scrape_tracker();
1177
 
                                }
1178
 
                        }
1179
 
                }
1180
 
 
1181
 
                // --------------------------------------------------------------
1182
 
                // connect new peers
1183
 
                // --------------------------------------------------------------
1184
 
 
1185
 
                // let torrents connect to peers if they want to
1186
 
                // if there are any torrents and any free slots
1187
 
 
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
1192
 
 
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
1197
 
                        && !m_abort)
1198
 
                {
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;
1205
 
 
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);
1209
 
                        else
1210
 
                                m_next_connect_torrent = 0;
1211
 
                        int steps_since_last_connect = 0;
1212
 
                        int num_torrents = int(m_torrents.size());
1213
 
                        for (;;)
1214
 
                        {
1215
 
                                torrent& t = *i->second;
1216
 
                                if (t.want_more_peers())
1217
 
                                {
1218
 
                                        int connect_points = 100;
1219
 
                                        // have a bias against torrents with more peers
1220
 
                                        // than average
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);
1233
 
                                        try
1234
 
                                        {
1235
 
                                                if (t.try_connect_peer())
1236
 
                                                {
1237
 
                                                        --max_connections;
1238
 
                                                        --free_slots;
1239
 
                                                        steps_since_last_connect = 0;
1240
 
                                                }
1241
 
                                        }
1242
 
                                        catch (std::bad_alloc&)
1243
 
                                        {
1244
 
                                                // we ran out of memory trying to connect to a peer
1245
 
                                                // lower the global limit to the number of peers
1246
 
                                                // we already have
1247
 
                                                m_max_connections = num_connections();
1248
 
                                                if (m_max_connections < 2) m_max_connections = 2;
1249
 
                                        }
1250
 
                                }
1251
 
                                ++m_next_connect_torrent;
1252
 
                                ++steps_since_last_connect;
1253
 
                                ++i;
1254
 
                                if (i == m_torrents.end())
1255
 
                                {
1256
 
                                        TORRENT_ASSERT(m_next_connect_torrent == num_torrents);
1257
 
                                        i = m_torrents.begin();
1258
 
                                        m_next_connect_torrent = 0;
1259
 
                                }
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;
1270
 
                        }
1271
 
                }
1272
 
 
1273
 
                // --------------------------------------------------------------
1274
 
                // auto managed torrent
1275
 
                // --------------------------------------------------------------
1276
 
                m_auto_manage_time_scaler--;
1277
 
                if (m_auto_manage_time_scaler <= 0)
1278
 
                {
1279
 
                        m_auto_manage_time_scaler = settings().auto_manage_interval;
1280
 
                        recalculate_auto_managed_torrents();
1281
 
                }
1282
 
 
1283
 
                // --------------------------------------------------------------
1284
 
                // unchoke set and optimistic unchoke calculations
1285
 
                // --------------------------------------------------------------
1286
 
                m_unchoke_time_scaler--;
1287
 
                if (m_unchoke_time_scaler <= 0 && !m_connections.empty())
1288
 
                {
1289
 
                        m_unchoke_time_scaler = settings().unchoke_interval;
1290
 
                        recalculate_unchoke_slots(congested_torrents
1291
 
                                , uncongested_torrents);
1292
 
                }
1293
 
 
1294
 
                // --------------------------------------------------------------
1295
 
                // disconnect peers when we have too many
1296
 
                // --------------------------------------------------------------
1297
 
                --m_disconnect_time_scaler;
1298
 
                if (m_disconnect_time_scaler <= 0)
1299
 
                {
1300
 
                        m_disconnect_time_scaler = 90;
1301
 
 
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())
1306
 
                        {
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)));
1310
 
                        
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);
1316
 
                        }
1317
 
                        else
1318
 
                        {
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)
1323
 
                                {
1324
 
                                        boost::shared_ptr<torrent> t = i->second;
1325
 
                                        if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff)
1326
 
                                                continue;
1327
 
 
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);
1332
 
                                }
1333
 
                        }
1334
 
                }
1335
 
        }
1336
 
 
1337
 
        namespace
1338
 
        {
1339
 
                bool is_active(torrent* t, session_settings const& s)
1340
 
                {
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));
1345
 
                }
1346
 
        }
1347
 
 
1348
 
        void session_impl::recalculate_auto_managed_torrents()
1349
 
        {
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());
1355
 
 
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;
1361
 
 
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)();
1368
 
            
1369
 
                for (torrent_map::iterator i = m_torrents.begin()
1370
 
                        , end(m_torrents.end()); i != end; ++i)
1371
 
                {
1372
 
                        torrent* t = i->second.get();
1373
 
                        TORRENT_ASSERT(t);
1374
 
                        if (t->is_auto_managed() && !t->has_error())
1375
 
                        {
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())
1379
 
                                        seeds.push_back(t);
1380
 
                                else
1381
 
                                        downloaders.push_back(t);
1382
 
                        }
1383
 
                        else if (!t->is_paused())
1384
 
                        {
1385
 
                                --hard_limit;
1386
 
                                if (is_active(t, settings()))
1387
 
                                {
1388
 
                                        // this is not an auto managed torrent,
1389
 
                                        // if it's running and active, decrease the
1390
 
                                        // counters.
1391
 
                                        --num_downloaders;
1392
 
                                        --num_seeds;
1393
 
                                }
1394
 
                        }
1395
 
                }
1396
 
 
1397
 
                bool handled_by_extension = false;
1398
 
 
1399
 
#ifndef TORRENT_DISABLE_EXTENSIONS
1400
 
                // TODO: allow extensions to sort torrents for queuing
1401
 
#endif
1402
 
 
1403
 
                if (!handled_by_extension)
1404
 
                {
1405
 
                        std::sort(downloaders.begin(), downloaders.end()
1406
 
                                , bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2));
1407
 
 
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)));
1411
 
                }
1412
 
 
1413
 
                for (std::vector<torrent*>::iterator i = downloaders.begin()
1414
 
                        , end(downloaders.end()); i != end; ++i)
1415
 
                {
1416
 
                        torrent* t = *i;
1417
 
                        if (!t->is_paused() && !is_active(t, settings())
1418
 
                                && hard_limit > 0)
1419
 
                        {
1420
 
                                --hard_limit;
1421
 
                                continue;
1422
 
                        }
1423
 
 
1424
 
                        if (num_downloaders > 0 && hard_limit > 0)
1425
 
                        {
1426
 
                                --hard_limit;
1427
 
                                --num_downloaders;
1428
 
                                if (t->is_paused()) t->resume();
1429
 
                        }
1430
 
                        else
1431
 
                        {
1432
 
                                if (!t->is_paused()) t->pause();
1433
 
                        }
1434
 
                }
1435
 
 
1436
 
                for (std::vector<torrent*>::iterator i = seeds.begin()
1437
 
                        , end(seeds.end()); i != end; ++i)
1438
 
                {
1439
 
                        torrent* t = *i;
1440
 
                        if (!t->is_paused() && !is_active(t, settings())
1441
 
                                && hard_limit > 0)
1442
 
                        {
1443
 
                                --hard_limit;
1444
 
                                continue;
1445
 
                        }
1446
 
 
1447
 
                        if (num_seeds > 0 && hard_limit > 0)
1448
 
                        {
1449
 
                                --hard_limit;
1450
 
                                --num_seeds;
1451
 
                                if (t->is_paused()) t->resume();
1452
 
                        }
1453
 
                        else
1454
 
                        {
1455
 
                                if (!t->is_paused()) t->pause();
1456
 
                        }
1457
 
                }
1458
 
        }
1459
 
 
1460
 
        void session_impl::recalculate_unchoke_slots(int congested_torrents
1461
 
                , int uncongested_torrents)
1462
 
        {
1463
 
                std::vector<peer_connection*> peers;
1464
 
                for (connection_map::iterator i = m_connections.begin()
1465
 
                        , end(m_connections.end()); i != end; ++i)
1466
 
                {
1467
 
                        peer_connection* p = i->get();
1468
 
                        TORRENT_ASSERT(p);
1469
 
                        torrent* t = p->associated_torrent().lock().get();
1470
 
                        if (!p->peer_info_struct()
1471
 
                                || t == 0
1472
 
                                || !p->is_peer_interested()
1473
 
                                || p->is_disconnecting()
1474
 
                                || p->is_connecting()
1475
 
                                || (p->share_diff() < -free_upload_amount
1476
 
                                        && !t->is_seed()))
1477
 
                        {
1478
 
                                if (!(*i)->is_choked() && t)
1479
 
                                {
1480
 
                                        policy::peer* pi = p->peer_info_struct();
1481
 
                                        if (pi && pi->optimistically_unchoked)
1482
 
                                        {
1483
 
                                                pi->optimistically_unchoked = false;
1484
 
                                                // force a new optimistic unchoke
1485
 
                                                m_optimistic_unchoke_time_scaler = 0;
1486
 
                                        }
1487
 
                                        t->choke_peer(*(*i));
1488
 
                                }
1489
 
                                continue;
1490
 
                        }
1491
 
                        peers.push_back(i->get());
1492
 
                }
1493
 
 
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
1497
 
                // be unchoked
1498
 
                std::sort(peers.begin(), peers.end()
1499
 
                        , bind(&peer_connection::unchoke_compare, _1, _2));
1500
 
 
1501
 
                std::for_each(m_connections.begin(), m_connections.end()
1502
 
                        , bind(&peer_connection::reset_choke_counters, _1));
1503
 
 
1504
 
                // auto unchoke
1505
 
                int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
1506
 
                if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf)
1507
 
                {
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
1511
 
                        // limit
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)
1516
 
                        {
1517
 
                                ++m_allowed_upload_slots;
1518
 
                        }
1519
 
                        else if (m_upload_channel.queue_size() > 1
1520
 
                                && m_allowed_upload_slots > m_max_uploads)
1521
 
                        {
1522
 
                                --m_allowed_upload_slots;
1523
 
                        }
1524
 
                }
1525
 
 
1526
 
                // reserve one upload slot for optimistic unchokes
1527
 
                int unchoke_set_size = m_allowed_upload_slots - 1;
1528
 
 
1529
 
                m_num_unchoked = 0;
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)
1534
 
                {
1535
 
                        peer_connection* p = *i;
1536
 
                        TORRENT_ASSERT(p);
1537
 
                        torrent* t = p->associated_torrent().lock().get();
1538
 
                        TORRENT_ASSERT(t);
1539
 
                        if (unchoke_set_size > 0)
1540
 
                        {
1541
 
                                if (p->is_choked())
1542
 
                                {
1543
 
                                        if (!t->unchoke_peer(*p))
1544
 
                                                continue;
1545
 
                                }
1546
 
 
1547
 
                                --unchoke_set_size;
1548
 
                                ++m_num_unchoked;
1549
 
 
1550
 
                                TORRENT_ASSERT(p->peer_info_struct());
1551
 
                                if (p->peer_info_struct()->optimistically_unchoked)
1552
 
                                {
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;
1558
 
                                }
1559
 
                        }
1560
 
                        else
1561
 
                        {
1562
 
                                TORRENT_ASSERT(p->peer_info_struct());
1563
 
                                if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
1564
 
                                        t->choke_peer(*p);
1565
 
                                if (!p->is_choked())
1566
 
                                        ++m_num_unchoked;
1567
 
                        }
1568
 
                }
1569
 
 
1570
 
                if (m_allowed_upload_slots > 0)
1571
 
                {
1572
 
                        m_optimistic_unchoke_time_scaler--;
1573
 
                        if (m_optimistic_unchoke_time_scaler <= 0)
1574
 
                        {
1575
 
                                m_optimistic_unchoke_time_scaler
1576
 
                                        = settings().optimistic_unchoke_multiplier;
1577
 
 
1578
 
                                // find the peer that has been waiting the longest to be optimistically
1579
 
                                // unchoked
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();
1583
 
 
1584
 
                                for (connection_map::iterator i = m_connections.begin()
1585
 
                                        , end(m_connections.end()); i != end; ++i)
1586
 
                                {
1587
 
                                        peer_connection* p = i->get();
1588
 
                                        TORRENT_ASSERT(p);
1589
 
                                        policy::peer* pi = p->peer_info_struct();
1590
 
                                        if (!pi) continue;
1591
 
                                        torrent* t = p->associated_torrent().lock().get();
1592
 
                                        if (!t) continue;
1593
 
 
1594
 
                                        if (pi->optimistically_unchoked)
1595
 
                                        {
1596
 
                                                TORRENT_ASSERT(!p->is_choked());
1597
 
                                                TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end());
1598
 
                                                current_optimistic_unchoke = i;
1599
 
                                        }
1600
 
 
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()
1606
 
                                                && p->is_choked()
1607
 
                                                && t->valid_metadata())
1608
 
                                        {
1609
 
                                                last_unchoke = pi->last_optimistically_unchoked;
1610
 
                                                optimistic_unchoke_candidate = i;
1611
 
                                        }
1612
 
                                }
1613
 
 
1614
 
                                if (optimistic_unchoke_candidate != m_connections.end()
1615
 
                                        && optimistic_unchoke_candidate != current_optimistic_unchoke)
1616
 
                                {
1617
 
                                        if (current_optimistic_unchoke != m_connections.end())
1618
 
                                        {
1619
 
                                                torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get();
1620
 
                                                TORRENT_ASSERT(t);
1621
 
                                                (*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false;
1622
 
                                                t->choke_peer(*current_optimistic_unchoke->get());
1623
 
                                        }
1624
 
                                        else
1625
 
                                        {
1626
 
                                                ++m_num_unchoked;
1627
 
                                        }
1628
 
 
1629
 
                                        torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get();
1630
 
                                        TORRENT_ASSERT(t);
1631
 
                                        bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get());
1632
 
                                        TORRENT_ASSERT(ret);
1633
 
                                        (*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true;
1634
 
                                }
1635
 
                        }
1636
 
                }
1637
 
        }
1638
 
 
1639
 
        void session_impl::operator()()
1640
 
        {
1641
 
                eh_initializer();
1642
 
 
1643
 
                {
1644
 
                        session_impl::mutex_t::scoped_lock l(m_mutex);
1645
 
                        if (m_listen_interface.port() != 0) open_listen_port();
1646
 
                }
1647
 
 
1648
 
                do
1649
 
                {
1650
 
                        error_code ec;
1651
 
                        m_io_service.run(ec);
1652
 
                        TORRENT_ASSERT(m_abort == true);
1653
 
                        if (ec)
1654
 
                        {
1655
 
#ifdef TORRENT_DEBUG
1656
 
                                std::cerr << ec.message() << "\n";
1657
 
                                std::string err = ec.message();
1658
 
#endif
1659
 
                                TORRENT_ASSERT(false);
1660
 
                        }
1661
 
                        m_io_service.reset();
1662
 
                }
1663
 
                while (!m_abort);
1664
 
 
1665
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1666
 
                (*m_logger) << time_now_string() << " locking mutex\n";
1667
 
#endif
1668
 
 
1669
 
                session_impl::mutex_t::scoped_lock l(m_mutex);
1670
 
/*
1671
 
#ifdef TORRENT_DEBUG
1672
 
                for (torrent_map::iterator i = m_torrents.begin();
1673
 
                        i != m_torrents.end(); ++i)
1674
 
                {
1675
 
                        TORRENT_ASSERT(i->second->num_peers() == 0);
1676
 
                }
1677
 
#endif
1678
 
*/
1679
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1680
 
                (*m_logger) << time_now_string() << " cleaning up torrents\n";
1681
 
#endif
1682
 
                m_torrents.clear();
1683
 
 
1684
 
                TORRENT_ASSERT(m_torrents.empty());
1685
 
                TORRENT_ASSERT(m_connections.empty());
1686
 
        }
1687
 
 
1688
 
 
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)
1692
 
        {
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)
1698
 
                {
1699
 
                        torrent* p = boost::get_pointer(j->second);
1700
 
                        TORRENT_ASSERT(p);
1701
 
                }
1702
 
#endif
1703
 
                if (i != m_torrents.end()) return i->second;
1704
 
                return boost::weak_ptr<torrent>();
1705
 
        }
1706
 
 
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)
1710
 
        {
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));
1713
 
        }
1714
 
#endif
1715
 
 
1716
 
        std::vector<torrent_handle> session_impl::get_torrents()
1717
 
        {
1718
 
                mutex_t::scoped_lock l(m_mutex);
1719
 
                std::vector<torrent_handle> ret;
1720
 
 
1721
 
                for (session_impl::torrent_map::iterator i
1722
 
                        = m_torrents.begin(), end(m_torrents.end());
1723
 
                        i != end; ++i)
1724
 
                {
1725
 
                        if (i->second->is_aborted()) continue;
1726
 
                        ret.push_back(torrent_handle(i->second));
1727
 
                }
1728
 
                return ret;
1729
 
        }
1730
 
 
1731
 
        torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash)
1732
 
        {
1733
 
                return torrent_handle(find_torrent(info_hash));
1734
 
        }
1735
 
 
1736
 
        torrent_handle session_impl::add_torrent(add_torrent_params const& params)
1737
 
        {
1738
 
                TORRENT_ASSERT(!params.save_path.empty());
1739
 
 
1740
 
                if (params.ti && params.ti->num_files() == 0)
1741
 
                {
1742
 
#ifndef BOOST_NO_EXCEPTIONS
1743
 
                        throw std::runtime_error("no files in torrent");
1744
 
#else
1745
 
                        return torrent_handle();
1746
 
#endif
1747
 
                }
1748
 
 
1749
 
                // lock the session and the checker thread (the order is important!)
1750
 
                mutex_t::scoped_lock l(m_mutex);
1751
 
 
1752
 
//              INVARIANT_CHECK;
1753
 
 
1754
 
                if (is_aborted())
1755
 
                {
1756
 
#ifndef BOOST_NO_EXCEPTIONS
1757
 
                        throw std::runtime_error("session is closing");
1758
 
#else
1759
 
                        return torrent_handle();
1760
 
#endif
1761
 
                }
1762
 
                
1763
 
                // figure out the info hash of the torrent
1764
 
                sha1_hash const* ih = 0;
1765
 
                if (params.ti) ih = &params.ti->info_hash();
1766
 
                else ih = &params.info_hash;
1767
 
 
1768
 
                // is the torrent already active?
1769
 
                boost::shared_ptr<torrent> torrent_ptr = find_torrent(*ih).lock();
1770
 
                if (torrent_ptr)
1771
 
                {
1772
 
                        if (!params.duplicate_is_error)
1773
 
                                return torrent_handle(torrent_ptr);
1774
 
 
1775
 
#ifndef BOOST_NO_EXCEPTIONS
1776
 
                        throw duplicate_torrent();
1777
 
#else
1778
 
                        return torrent_handle();
1779
 
#endif
1780
 
                }
1781
 
 
1782
 
                int queue_pos = 0;
1783
 
                for (torrent_map::const_iterator i = m_torrents.begin()
1784
 
                        , end(m_torrents.end()); i != end; ++i)
1785
 
                {
1786
 
                        int pos = i->second->queue_position();
1787
 
                        if (pos >= queue_pos) queue_pos = pos + 1;
1788
 
                }
1789
 
 
1790
 
                // create the torrent and the data associated with
1791
 
                // the checker thread and store it before starting
1792
 
                // the thread
1793
 
                if (params.ti)
1794
 
                {
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));
1799
 
                }
1800
 
                else
1801
 
                {
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));
1806
 
                }
1807
 
                torrent_ptr->start();
1808
 
 
1809
 
#ifndef TORRENT_DISABLE_EXTENSIONS
1810
 
                for (extension_list_t::iterator i = m_extensions.begin()
1811
 
                        , end(m_extensions.end()); i != end; ++i)
1812
 
                {
1813
 
                        boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get(), params.userdata));
1814
 
                        if (tp) torrent_ptr->add_extension(tp);
1815
 
                }
1816
 
#endif
1817
 
 
1818
 
#ifndef TORRENT_DISABLE_DHT
1819
 
                if (m_dht && params.ti)
1820
 
                {
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));
1826
 
                }
1827
 
#endif
1828
 
 
1829
 
                m_torrents.insert(std::make_pair(*ih, torrent_ptr));
1830
 
 
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;
1835
 
 
1836
 
                return torrent_handle(torrent_ptr);
1837
 
        }
1838
 
 
1839
 
        void session_impl::check_torrent(boost::shared_ptr<torrent> const& t)
1840
 
        {
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);
1849
 
        }
1850
 
 
1851
 
        void session_impl::done_checking(boost::shared_ptr<torrent> const& t)
1852
 
        {
1853
 
                INVARIANT_CHECK;
1854
 
 
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)
1860
 
                {
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())
1864
 
                                next_check = *i;
1865
 
                }
1866
 
                // only start a new one if we removed the one that is checking
1867
 
                if (done == m_queued_for_checking.end()) return;
1868
 
 
1869
 
                if (next_check != t && t->state() == torrent_status::checking_files)
1870
 
                        next_check->start_checking();
1871
 
                m_queued_for_checking.erase(done);
1872
 
        }
1873
 
 
1874
 
        void session_impl::remove_torrent(const torrent_handle& h, int options)
1875
 
        {
1876
 
                boost::shared_ptr<torrent> tptr = h.m_torrent.lock();
1877
 
                if (!tptr)
1878
 
#ifdef BOOST_NO_EXCEPTIONS
1879
 
                        return;
1880
 
#else
1881
 
                        throw invalid_handle();
1882
 
#endif
1883
 
 
1884
 
                mutex_t::scoped_lock l(m_mutex);
1885
 
 
1886
 
                INVARIANT_CHECK;
1887
 
 
1888
 
                session_impl::torrent_map::iterator i =
1889
 
                        m_torrents.find(tptr->torrent_file().info_hash());
1890
 
 
1891
 
                if (i != m_torrents.end())
1892
 
                {
1893
 
                        torrent& t = *i->second;
1894
 
                        if (options & session::delete_files)
1895
 
                                t.delete_files();
1896
 
                        t.abort();
1897
 
 
1898
 
#ifdef TORRENT_DEBUG
1899
 
                        sha1_hash i_hash = t.torrent_file().info_hash();
1900
 
#endif
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());
1907
 
                        return;
1908
 
                }
1909
 
        }
1910
 
 
1911
 
        bool session_impl::listen_on(
1912
 
                std::pair<int, int> const& port_range
1913
 
                , const char* net_interface)
1914
 
        {
1915
 
                session_impl::mutex_t::scoped_lock l(m_mutex);
1916
 
 
1917
 
                INVARIANT_CHECK;
1918
 
 
1919
 
                tcp::endpoint new_interface;
1920
 
                if (net_interface && std::strlen(net_interface) > 0)
1921
 
                {
1922
 
                        error_code ec;
1923
 
                        new_interface = tcp::endpoint(address::from_string(net_interface, ec), port_range.first);
1924
 
                        if (ec)
1925
 
                        {
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";
1929
 
#endif
1930
 
                                return false;
1931
 
                        }
1932
 
                }
1933
 
                else
1934
 
                        new_interface = tcp::endpoint(address_v4::any(), port_range.first);
1935
 
 
1936
 
                m_listen_port_retries = port_range.second - port_range.first;
1937
 
 
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;
1942
 
 
1943
 
                m_listen_interface = new_interface;
1944
 
 
1945
 
                open_listen_port();
1946
 
 
1947
 
                bool new_listen_address = m_listen_interface.address() != new_interface.address();
1948
 
 
1949
 
#ifndef TORRENT_DISABLE_DHT
1950
 
                if ((new_listen_address || m_dht_same_port) && m_dht)
1951
 
                {
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);
1956
 
                        if (m_natpmp.get())
1957
 
                        {
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);
1962
 
                        }
1963
 
                        if (m_upnp.get())
1964
 
                        {
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);
1969
 
                        }
1970
 
                }
1971
 
#endif
1972
 
 
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";
1976
 
#endif
1977
 
 
1978
 
                return !m_listen_sockets.empty();
1979
 
        }
1980
 
 
1981
 
        unsigned short session_impl::listen_port() const
1982
 
        {
1983
 
                mutex_t::scoped_lock l(m_mutex);
1984
 
                if (m_listen_sockets.empty()) return 0;
1985
 
                return m_listen_sockets.front().external_port;;
1986
 
        }
1987
 
 
1988
 
        void session_impl::announce_lsd(sha1_hash const& ih)
1989
 
        {
1990
 
                mutex_t::scoped_lock l(m_mutex);
1991
 
                // use internal listen port for local peers
1992
 
                if (m_lsd.get())
1993
 
                        m_lsd->announce(ih, m_listen_interface.port());
1994
 
        }
1995
 
 
1996
 
        void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih)
1997
 
        {
1998
 
                mutex_t::scoped_lock l(m_mutex);
1999
 
 
2000
 
                INVARIANT_CHECK;
2001
 
 
2002
 
                boost::shared_ptr<torrent> t = find_torrent(ih).lock();
2003
 
                if (!t) return;
2004
 
                // don't add peers from lsd to private torrents
2005
 
                if (t->torrent_file().priv()) return;
2006
 
 
2007
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2008
 
                (*m_logger) << time_now_string()
2009
 
                        << ": added peer from local discovery: " << peer << "\n";
2010
 
#endif
2011
 
                t->get_policy().peer_from_tracker(peer, peer_id(0), peer_info::lsd, 0);
2012
 
        }
2013
 
 
2014
 
        void session_impl::on_port_mapping(int mapping, int port
2015
 
                , std::string const& errmsg, int map_transport)
2016
 
        {
2017
 
#ifndef TORRENT_DISABLE_DHT
2018
 
                if (mapping == m_udp_mapping[map_transport] && port != 0)
2019
 
                {
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
2024
 
                                        , map_transport));
2025
 
                        return;
2026
 
                }
2027
 
#endif
2028
 
 
2029
 
                if (mapping == m_tcp_mapping[map_transport] && port != 0)
2030
 
                {
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
2035
 
                                        , map_transport));
2036
 
                        return;
2037
 
                }
2038
 
 
2039
 
                if (!errmsg.empty())
2040
 
                {
2041
 
                        if (m_alerts.should_post<portmap_error_alert>())
2042
 
                                m_alerts.post_alert(portmap_error_alert(mapping
2043
 
                                        , map_transport, errmsg));
2044
 
                }
2045
 
                else
2046
 
                {
2047
 
                        if (m_alerts.should_post<portmap_alert>())
2048
 
                                m_alerts.post_alert(portmap_alert(mapping, port
2049
 
                                        , map_transport));
2050
 
                }
2051
 
        }
2052
 
 
2053
 
        session_status session_impl::status() const
2054
 
        {
2055
 
                mutex_t::scoped_lock l(m_mutex);
2056
 
 
2057
 
//              INVARIANT_CHECK;
2058
 
 
2059
 
                session_status s;
2060
 
 
2061
 
                s.num_peers = (int)m_connections.size();
2062
 
                s.num_unchoked = m_num_unchoked;
2063
 
                s.allowed_upload_slots = m_allowed_upload_slots;
2064
 
 
2065
 
                s.total_redundant_bytes = m_total_redundant_bytes;
2066
 
                s.total_failed_bytes = m_total_failed_bytes;
2067
 
 
2068
 
                s.up_bandwidth_queue = m_upload_channel.queue_size();
2069
 
                s.down_bandwidth_queue = m_download_channel.queue_size();
2070
 
 
2071
 
                s.has_incoming_connections = m_incoming_connection;
2072
 
 
2073
 
                s.download_rate = m_stat.download_rate();
2074
 
                s.upload_rate = m_stat.upload_rate();
2075
 
 
2076
 
                s.payload_download_rate = m_stat.download_payload_rate();
2077
 
                s.payload_upload_rate = m_stat.upload_payload_rate();
2078
 
 
2079
 
                s.total_download = m_stat.total_protocol_download()
2080
 
                        + m_stat.total_payload_download();
2081
 
 
2082
 
                s.total_upload = m_stat.total_protocol_upload()
2083
 
                        + m_stat.total_payload_upload();
2084
 
 
2085
 
                s.total_payload_download = m_stat.total_payload_download();
2086
 
                s.total_payload_upload = m_stat.total_payload_upload();
2087
 
 
2088
 
#ifndef TORRENT_DISABLE_DHT
2089
 
                if (m_dht)
2090
 
                {
2091
 
                        m_dht->dht_status(s);
2092
 
                }
2093
 
                else
2094
 
                {
2095
 
                        s.dht_nodes = 0;
2096
 
                        s.dht_node_cache = 0;
2097
 
                        s.dht_torrents = 0;
2098
 
                        s.dht_global_nodes = 0;
2099
 
                }
2100
 
#endif
2101
 
 
2102
 
                return s;
2103
 
        }
2104
 
 
2105
 
#ifndef TORRENT_DISABLE_DHT
2106
 
 
2107
 
        void session_impl::start_dht(entry const& startup_state)
2108
 
        {
2109
 
                mutex_t::scoped_lock l(m_mutex);
2110
 
 
2111
 
                INVARIANT_CHECK;
2112
 
 
2113
 
                if (m_dht)
2114
 
                {
2115
 
                        m_dht->stop();
2116
 
                        m_dht = 0;
2117
 
                }
2118
 
                if (m_dht_settings.service_port == 0
2119
 
                        || m_dht_same_port)
2120
 
                {
2121
 
                        m_dht_same_port = true;
2122
 
                        if (m_listen_interface.port() > 0)
2123
 
                                m_dht_settings.service_port = m_listen_interface.port();
2124
 
                        else
2125
 
                                m_dht_settings.service_port = 45000 + (rand() % 10000);
2126
 
                }
2127
 
                m_external_udp_port = m_dht_settings.service_port;
2128
 
                if (m_natpmp.get() && m_udp_mapping[0] == -1)
2129
 
                {
2130
 
                        m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2131
 
                                , m_dht_settings.service_port
2132
 
                                , m_dht_settings.service_port);
2133
 
                }
2134
 
                if (m_upnp.get() && m_udp_mapping[1] == -1)
2135
 
                {
2136
 
                        m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2137
 
                                , m_dht_settings.service_port
2138
 
                                , m_dht_settings.service_port);
2139
 
                }
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)
2142
 
                {
2143
 
                        m_dht_socket.bind(m_dht_settings.service_port);
2144
 
                }
2145
 
 
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)
2148
 
                {
2149
 
                        m_dht->add_router_node(*i);
2150
 
                }
2151
 
                std::list<std::pair<std::string, int> >().swap(m_dht_router_nodes);
2152
 
 
2153
 
                m_dht->start(startup_state);
2154
 
        }
2155
 
 
2156
 
        void session_impl::stop_dht()
2157
 
        {
2158
 
                mutex_t::scoped_lock l(m_mutex);
2159
 
                if (!m_dht) return;
2160
 
                m_dht->stop();
2161
 
                m_dht = 0;
2162
 
        }
2163
 
 
2164
 
        void session_impl::set_dht_settings(dht_settings const& settings)
2165
 
        {
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;
2172
 
                else
2173
 
                        m_dht_same_port = true;
2174
 
                if (!m_dht_same_port
2175
 
                        && settings.service_port != m_dht_settings.service_port
2176
 
                        && m_dht)
2177
 
                {
2178
 
                        m_dht_socket.bind(settings.service_port);
2179
 
 
2180
 
                        if (m_natpmp.get())
2181
 
                        {
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);
2186
 
                        }
2187
 
                        if (m_upnp.get())
2188
 
                        {
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);
2193
 
                        }
2194
 
                        m_external_udp_port = settings.service_port;
2195
 
                }
2196
 
                m_dht_settings = settings;
2197
 
                if (m_dht_same_port)
2198
 
                        m_dht_settings.service_port = m_listen_interface.port();
2199
 
        }
2200
 
 
2201
 
        void session_impl::dht_state_callback(boost::condition& c
2202
 
                , entry& e, bool& done) const
2203
 
        {
2204
 
                mutex_t::scoped_lock l(m_mutex);
2205
 
                if (m_dht) e = m_dht->state();
2206
 
                done = true;
2207
 
                c.notify_all();
2208
 
        }
2209
 
 
2210
 
        entry session_impl::dht_state() const
2211
 
        {
2212
 
                boost::condition cond;
2213
 
                mutex_t::scoped_lock l(m_mutex);
2214
 
                if (!m_dht) return entry();
2215
 
                entry e;
2216
 
                bool done = false;
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);
2220
 
                return e;
2221
 
        }
2222
 
 
2223
 
        void session_impl::add_dht_node(std::pair<std::string, int> const& node)
2224
 
        {
2225
 
                TORRENT_ASSERT(m_dht);
2226
 
                mutex_t::scoped_lock l(m_mutex);
2227
 
                m_dht->add_node(node);
2228
 
        }
2229
 
 
2230
 
        void session_impl::add_dht_router(std::pair<std::string, int> const& node)
2231
 
        {
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);
2236
 
        }
2237
 
 
2238
 
#endif
2239
 
 
2240
 
#ifndef TORRENT_DISABLE_ENCRYPTION
2241
 
        void session_impl::set_pe_settings(pe_settings const& settings)
2242
 
        {
2243
 
                mutex_t::scoped_lock l(m_mutex);
2244
 
                m_pe_settings = settings;
2245
 
        }
2246
 
#endif
2247
 
 
2248
 
        bool session_impl::is_listening() const
2249
 
        {
2250
 
                mutex_t::scoped_lock l(m_mutex);
2251
 
                return !m_listen_sockets.empty();
2252
 
        }
2253
 
 
2254
 
        session_impl::~session_impl()
2255
 
        {
2256
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2257
 
                (*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
2258
 
#endif
2259
 
                abort();
2260
 
                TORRENT_ASSERT(m_connections.empty());
2261
 
 
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";
2270
 
#endif
2271
 
                m_disk_thread.join();
2272
 
 
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);
2276
 
#endif
2277
 
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2278
 
                (*m_logger) << time_now_string() << " waiting for main thread\n";
2279
 
#endif
2280
 
                m_thread->join();
2281
 
 
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";
2286
 
#endif
2287
 
                TORRENT_ASSERT(m_connections.empty());
2288
 
        }
2289
 
 
2290
 
        void session_impl::set_max_uploads(int limit)
2291
 
        {
2292
 
                TORRENT_ASSERT(limit >= 0 || limit == -1);
2293
 
                mutex_t::scoped_lock l(m_mutex);
2294
 
 
2295
 
                INVARIANT_CHECK;
2296
 
 
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;
2301
 
        }
2302
 
 
2303
 
        void session_impl::set_max_connections(int limit)
2304
 
        {
2305
 
                TORRENT_ASSERT(limit > 0 || limit == -1);
2306
 
                mutex_t::scoped_lock l(m_mutex);
2307
 
 
2308
 
                INVARIANT_CHECK;
2309
 
 
2310
 
                if (limit <= 0)
2311
 
                {
2312
 
                        limit = (std::numeric_limits<int>::max)();
2313
 
#ifndef TORRENT_WINDOWS
2314
 
                        rlimit l;
2315
 
                        if (getrlimit(RLIMIT_NOFILE, &l) == 0
2316
 
                                && l.rlim_cur != RLIM_INFINITY)
2317
 
                        {
2318
 
                                limit = l.rlim_cur - m_settings.file_pool_size;
2319
 
                                if (limit < 5) limit = 5;
2320
 
                        }
2321
 
#endif
2322
 
                }
2323
 
                m_max_connections = limit;
2324
 
        }
2325
 
 
2326
 
        void session_impl::set_max_half_open_connections(int limit)
2327
 
        {
2328
 
                TORRENT_ASSERT(limit > 0 || limit == -1);
2329
 
                mutex_t::scoped_lock l(m_mutex);
2330
 
 
2331
 
                INVARIANT_CHECK;
2332
 
 
2333
 
                if (limit <= 0) limit = (std::numeric_limits<int>::max)();
2334
 
                m_half_open.limit(limit);
2335
 
        }
2336
 
 
2337
 
        void session_impl::set_download_rate_limit(int bytes_per_second)
2338
 
        {
2339
 
                TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1);
2340
 
                mutex_t::scoped_lock l(m_mutex);
2341
 
 
2342
 
                INVARIANT_CHECK;
2343
 
 
2344
 
                if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
2345
 
                m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second);
2346
 
        }
2347
 
 
2348
 
        void session_impl::set_upload_rate_limit(int bytes_per_second)
2349
 
        {
2350
 
                TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1);
2351
 
                mutex_t::scoped_lock l(m_mutex);
2352
 
 
2353
 
                INVARIANT_CHECK;
2354
 
 
2355
 
                if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
2356
 
                m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second);
2357
 
        }
2358
 
 
2359
 
        std::auto_ptr<alert> session_impl::pop_alert()
2360
 
        {
2361
 
                mutex_t::scoped_lock l(m_mutex);
2362
 
 
2363
 
// too expensive
2364
 
//              INVARIANT_CHECK;
2365
 
 
2366
 
                if (m_alerts.pending())
2367
 
                        return m_alerts.get();
2368
 
                return std::auto_ptr<alert>(0);
2369
 
        }
2370
 
        
2371
 
        alert const* session_impl::wait_for_alert(time_duration max_wait)
2372
 
        {
2373
 
                return m_alerts.wait_for_alert(max_wait);
2374
 
        }
2375
 
 
2376
 
        void session_impl::set_alert_mask(int m)
2377
 
        {
2378
 
                mutex_t::scoped_lock l(m_mutex);
2379
 
                m_alerts.set_alert_mask(m);
2380
 
        }
2381
 
 
2382
 
        size_t session_impl::set_alert_queue_size_limit(size_t queue_size_limit_)
2383
 
        {
2384
 
                mutex_t::scoped_lock l(m_mutex);
2385
 
                return m_alerts.set_alert_queue_size_limit(queue_size_limit_);
2386
 
        }
2387
 
 
2388
 
        int session_impl::upload_rate_limit() const
2389
 
        {
2390
 
                mutex_t::scoped_lock l(m_mutex);
2391
 
 
2392
 
                INVARIANT_CHECK;
2393
 
 
2394
 
                int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
2395
 
                return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
2396
 
        }
2397
 
 
2398
 
        int session_impl::download_rate_limit() const
2399
 
        {
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;
2403
 
        }
2404
 
 
2405
 
        void session_impl::start_lsd()
2406
 
        {
2407
 
                mutex_t::scoped_lock l(m_mutex);
2408
 
 
2409
 
                INVARIANT_CHECK;
2410
 
 
2411
 
                if (m_lsd) return;
2412
 
 
2413
 
                m_lsd = new lsd(m_io_service
2414
 
                        , m_listen_interface.address()
2415
 
                        , bind(&session_impl::on_lsd_peer, this, _1, _2));
2416
 
        }
2417
 
        
2418
 
        natpmp* session_impl::start_natpmp()
2419
 
        {
2420
 
                mutex_t::scoped_lock l(m_mutex);
2421
 
 
2422
 
                INVARIANT_CHECK;
2423
 
 
2424
 
                if (m_natpmp) return m_natpmp.get();
2425
 
 
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));
2430
 
 
2431
 
                if (m_listen_interface.port() > 0)
2432
 
                {
2433
 
                        m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
2434
 
                                , m_listen_interface.port(), m_listen_interface.port());
2435
 
                }
2436
 
#ifndef TORRENT_DISABLE_DHT
2437
 
                if (m_dht)
2438
 
                        m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2439
 
                                , m_dht_settings.service_port 
2440
 
                                , m_dht_settings.service_port);
2441
 
#endif
2442
 
                return m_natpmp.get();
2443
 
        }
2444
 
 
2445
 
        upnp* session_impl::start_upnp()
2446
 
        {
2447
 
                mutex_t::scoped_lock l(m_mutex);
2448
 
 
2449
 
                INVARIANT_CHECK;
2450
 
 
2451
 
                if (m_upnp) return m_upnp.get();
2452
 
 
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);
2459
 
 
2460
 
                m_upnp->discover_device();
2461
 
                if (m_listen_interface.port() > 0)
2462
 
                {
2463
 
                        m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp
2464
 
                                , m_listen_interface.port(), m_listen_interface.port());
2465
 
                }
2466
 
#ifndef TORRENT_DISABLE_DHT
2467
 
                if (m_dht)
2468
 
                        m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2469
 
                                , m_dht_settings.service_port 
2470
 
                                , m_dht_settings.service_port);
2471
 
#endif
2472
 
                return m_upnp.get();
2473
 
        }
2474
 
 
2475
 
        void session_impl::stop_lsd()
2476
 
        {
2477
 
                mutex_t::scoped_lock l(m_mutex);
2478
 
                if (m_lsd.get())
2479
 
                        m_lsd->close();
2480
 
                m_lsd = 0;
2481
 
        }
2482
 
        
2483
 
        void session_impl::stop_natpmp()
2484
 
        {
2485
 
                mutex_t::scoped_lock l(m_mutex);
2486
 
                if (m_natpmp.get())
2487
 
                        m_natpmp->close();
2488
 
                m_natpmp = 0;
2489
 
        }
2490
 
        
2491
 
        void session_impl::stop_upnp()
2492
 
        {
2493
 
                mutex_t::scoped_lock l(m_mutex);
2494
 
                if (m_upnp.get())
2495
 
                {
2496
 
                        m_upnp->close();
2497
 
                        m_udp_mapping[1] = -1;
2498
 
                        m_tcp_mapping[1] = -1;
2499
 
                }
2500
 
                m_upnp = 0;
2501
 
        }
2502
 
        
2503
 
        void session_impl::set_external_address(address const& ip)
2504
 
        {
2505
 
                TORRENT_ASSERT(ip != address());
2506
 
 
2507
 
                if (is_local(ip)) return;
2508
 
                if (is_loopback(ip)) return;
2509
 
                if (m_external_address == ip) return;
2510
 
 
2511
 
                m_external_address = ip;
2512
 
                if (m_alerts.should_post<external_ip_alert>())
2513
 
                        m_alerts.post_alert(external_ip_alert(ip));
2514
 
        }
2515
 
 
2516
 
        void session_impl::free_disk_buffer(char* buf)
2517
 
        {
2518
 
                m_disk_thread.free_buffer(buf);
2519
 
        }
2520
 
 
2521
 
        char* session_impl::allocate_disk_buffer()
2522
 
        {
2523
 
                return m_disk_thread.allocate_buffer();
2524
 
        }
2525
 
        
2526
 
        std::pair<char*, int> session_impl::allocate_buffer(int size)
2527
 
        {
2528
 
                TORRENT_ASSERT(size > 0);
2529
 
                int num_buffers = (size + send_buffer_size - 1) / send_buffer_size;
2530
 
                TORRENT_ASSERT(num_buffers > 0);
2531
 
 
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;
2538
 
#endif
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);
2542
 
#else
2543
 
                return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers)
2544
 
                        , num_buffers * send_buffer_size);
2545
 
#endif
2546
 
        }
2547
 
 
2548
 
#ifdef TORRENT_STATS
2549
 
        void session_impl::log_buffer_usage()
2550
 
        {
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)
2555
 
                {
2556
 
                        send_buffer_capacity += (*i)->send_buffer_capacity();
2557
 
                        used_send_buffer += (*i)->send_buffer_size();
2558
 
                }
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;
2564
 
        }
2565
 
#endif
2566
 
 
2567
 
        void session_impl::free_buffer(char* buf, int size)
2568
 
        {
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);
2573
 
 
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;
2580
 
#endif
2581
 
#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
2582
 
                free(buf);
2583
 
#else
2584
 
                m_send_buffers.ordered_free(buf, num_buffers);
2585
 
#endif
2586
 
        }       
2587
 
 
2588
 
#ifdef TORRENT_DEBUG
2589
 
        void session_impl::check_invariant() const
2590
 
        {
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)
2595
 
                {
2596
 
                        int pos = i->second->queue_position();
2597
 
                        if (pos < 0)
2598
 
                        {
2599
 
                                TORRENT_ASSERT(pos == -1);
2600
 
                                continue;
2601
 
                        }
2602
 
                        ++total_downloaders;
2603
 
                        unique.insert(i->second->queue_position());
2604
 
                }
2605
 
                TORRENT_ASSERT(int(unique.size()) == total_downloaders);
2606
 
 
2607
 
                TORRENT_ASSERT(m_max_connections > 0);
2608
 
                TORRENT_ASSERT(m_max_uploads >= 0);
2609
 
                TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads);
2610
 
                int unchokes = 0;
2611
 
                int num_optimistic = 0;
2612
 
                for (connection_map::const_iterator i = m_connections.begin();
2613
 
                        i != m_connections.end(); ++i)
2614
 
                {
2615
 
                        TORRENT_ASSERT(*i);
2616
 
                        boost::shared_ptr<torrent> t = (*i)->associated_torrent().lock();
2617
 
 
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)
2623
 
                        {
2624
 
                                ++num_optimistic;
2625
 
                                TORRENT_ASSERT(!p->is_choked());
2626
 
                        }
2627
 
                        if (t && p->peer_info_struct())
2628
 
                        {
2629
 
                                TORRENT_ASSERT(t->get_policy().has_connection(p));
2630
 
                        }
2631
 
                }
2632
 
                TORRENT_ASSERT(num_optimistic == 0 || num_optimistic == 1);
2633
 
                if (m_num_unchoked != unchokes)
2634
 
                {
2635
 
                        TORRENT_ASSERT(false);
2636
 
                }
2637
 
                for (std::map<sha1_hash, boost::shared_ptr<torrent> >::const_iterator j
2638
 
                        = m_torrents.begin(); j != m_torrents.end(); ++j)
2639
 
                {
2640
 
                        TORRENT_ASSERT(boost::get_pointer(j->second));
2641
 
                }
2642
 
        }
2643
 
#endif
2644
 
 
2645
 
}}
2646