source: trunk/src/halSession.hpp @ 780

Revision 780, 28.2 KB checked in by Eoin, 10 years ago (diff)

Archive supports Boost .40. Some 64bit casts added.

RevLine 
[479]1
[690]2//         Copyright Eóin O'Callaghan 2006 - 2009.
[479]3// Distributed under the Boost Software License, Version 1.0.
4//    (See accompanying file LICENSE_1_0.txt or copy at
5//          http://www.boost.org/LICENSE_1_0.txt)
6
7#pragma once
8
9#include <boost/tuple/tuple.hpp>
10#include <boost/enable_shared_from_this.hpp>
11#include <boost/multi_index_container.hpp>
12#include <boost/multi_index/ordered_index.hpp>
13#include <boost/multi_index/indexed_by.hpp>
14#include <boost/multi_index/identity.hpp>
15#include <boost/multi_index/member.hpp>
16#include <boost/multi_index/tag.hpp>
17
[573]18#pragma warning (push, 1)
19#       include <libtorrent/file.hpp>
20#       include <libtorrent/hasher.hpp>
21#       include <libtorrent/storage.hpp>
22#       include <libtorrent/file_pool.hpp>
23#       include <libtorrent/alert_types.hpp>
24#       include <libtorrent/entry.hpp>
25#       include <libtorrent/bencode.hpp>
[618]26#       include <libtorrent/upnp.hpp>
27#       include <libtorrent/natpmp.hpp>
[573]28#       include <libtorrent/session.hpp>
29#       include <libtorrent/ip_filter.hpp>
30#       include <libtorrent/torrent_handle.hpp>
31#       include <libtorrent/peer_connection.hpp>
32#       include <libtorrent/extensions/metadata_transfer.hpp>
33#       include <libtorrent/extensions/ut_pex.hpp>
[641]34#       include <libtorrent/extensions/ut_metadata.hpp>
35#       include <libtorrent/extensions/smart_ban.hpp>
[573]36#pragma warning (pop)
37
[479]38#include "halIni.hpp"
39#include "halTypes.hpp"
40#include "halEvent.hpp"
[660]41#include "halConfig.hpp"
[480]42#include "halTorrentInternal.hpp"
[741]43#include "halTorrentManager.hpp"
[479]44#include "halSignaler.hpp"
[746]45#include "halCatchDefines.hpp"
[479]46
[480]47namespace boost {
48namespace serialization {
49
50template<class Archive, class address_type>
51void save(Archive& ar, const address_type& ip, const unsigned int version)
52{       
53        unsigned long addr = ip.to_ulong();     
54        ar & BOOST_SERIALIZATION_NVP(addr);
55}
56
57template<class Archive, class address_type>
58void load(Archive& ar, address_type& ip, const unsigned int version)
59{       
60        unsigned long addr;
61        ar & BOOST_SERIALIZATION_NVP(addr);     
62        ip = address_type(addr);
63}
64
65template<class Archive, class String, class Traits>
66void save(Archive& ar, const boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
67{       
68        String str = p.string();
69        ar & BOOST_SERIALIZATION_NVP(str);
70}
71
72template<class Archive, class String, class Traits>
73void load(Archive& ar, boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
74{       
75        String str;
76        ar & BOOST_SERIALIZATION_NVP(str);
77
78        p = str;
79}
80
81template<class Archive, class String, class Traits>
82inline void serialize(
83        Archive & ar,
84        boost::filesystem::basic_path<String, Traits>& p,
[503]85        const unsigned int file_version)
86{
[480]87        split_free(ar, p, file_version);           
88}
89
90template<class Archive, class address_type>
91void serialize(Archive& ar, libtorrent::ip_range<address_type>& addr, const unsigned int version)
92{       
93        ar & BOOST_SERIALIZATION_NVP(addr.first);
94        ar & BOOST_SERIALIZATION_NVP(addr.last);
95        addr.flags = libtorrent::ip_filter::blocked;
96}
97
98template<class Archive>
99void serialize(Archive& ar, hal::tracker_detail& tracker, const unsigned int version)
100{       
101        ar & BOOST_SERIALIZATION_NVP(tracker.url);
102        ar & BOOST_SERIALIZATION_NVP(tracker.tier);
103}
104
105} // namespace serialization
106} // namespace boost
107
108BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v4)
109BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v6)
110
111namespace libtorrent
112{
113
114template<class Addr>
115bool operator==(const libtorrent::ip_range<Addr>& lhs, const int flags)
116{
117        return (lhs.flags == flags);
118}
119
[745]120inline std::ostream& operator<<(std::ostream& os, libtorrent::ip_range<asio::ip::address_v4>& ip)
[480]121{
122        os << ip.first.to_ulong();
123        os << ip.last.to_ulong();
124       
125        return os;
126}
127
128} // namespace libtorrent
129
[479]130namespace hal
131{
132
[480]133namespace libt = libtorrent;
134
[745]135inline bool operator!=(const libt::dht_settings& lhs, const libt::dht_settings& rhs)
[479]136{
137        return lhs.max_peers_reply != rhs.max_peers_reply ||
138                   lhs.search_branching != rhs.search_branching ||
139                   lhs.service_port != rhs.service_port ||
140           lhs.max_fail_count != rhs.max_fail_count;
141}
142
143template<typename Addr>
144void write_range(fs::ofstream& ofs, const libt::ip_range<Addr>& range)
145{ 
146        const typename Addr::bytes_type first = range.first.to_bytes();
147        const typename Addr::bytes_type last = range.last.to_bytes();
148        ofs.write((char*)first.elems, first.size());
149        ofs.write((char*)last.elems, last.size());
150}
151
152template<typename Addr>
153void write_vec_range(fs::ofstream& ofs, const std::vector<libt::ip_range<Addr> >& vec)
154{ 
155        ofs << vec.size();
156       
157        for (typename std::vector<libt::ip_range<Addr> >::const_iterator i=vec.begin(); 
158                i != vec.end(); ++i)
159        {
160                write_range(ofs, *i);
161        }
162}
163
164template<typename Addr>
165void read_range_to_filter(fs::ifstream& ifs, libt::ip_filter& ip_filter)
166{ 
167        typename Addr::bytes_type first;
168        typename Addr::bytes_type last;
169        ifs.read((char*)first.elems, first.size());
170        ifs.read((char*)last.elems, last.size());       
171       
172        ip_filter.add_rule(Addr(first), Addr(last),
173                libt::ip_filter::blocked);
174}
175
176static event_logger::eventLevel lbtAlertToHalEvent(libt::alert::severity_t severity)
177{
178        switch (severity)
179        {
180        case libt::alert::debug:
181                return event_logger::debug;
182       
183        case libt::alert::info:
184                return event_logger::info;
185       
186        case libt::alert::warning:
187                return event_logger::warning;
188       
189        case libt::alert::critical:
190        case libt::alert::fatal:
191                return event_logger::critical;
192       
193        default:
194                return event_logger::none;
195        }
196}
197
[571]198static event_logger::eventLevel lbt_category_to_event(int category)
199{
200        switch (category)
201        {
202        case libt::alert::debug_notification:
203                return event_logger::debug;
204       
205        case libt::alert::peer_notification:
206        case libt::alert::port_mapping_notification:
207        case libt::alert::storage_notification:
208        case libt::alert::tracker_notification:
209        case libt::alert::status_notification:
210        case libt::alert::progress_notification:
211        case libt::alert::ip_block_notification:
212                return event_logger::info;
213       
214        case libt::alert::performance_warning:
215                return event_logger::warning;
216       
217        case libt::alert::error_notification:
218                return event_logger::critical;
219       
220        default:
221                return event_logger::none;
222        }
223}
224
[746]225struct uninitialized;
[570]226
[745]227class bit_impl :
[746]228        public sc::state_machine<bit_impl, uninitialized>
[479]229{
230        friend class bit;
231
[503]232private:
[746]233        bit_impl();
234
[503]235public: 
236        ~bit_impl();
[479]237
[482]238        bool listen_on(std::pair<int, int> const& range)
[479]239        {
[480]240                try
[479]241                {
242               
[746]243                if (!session_->is_listening())
[479]244                {
[746]245                        return session_->listen_on(range);
[480]246                }
247                else
[479]248                {
[746]249                        int port = session_->listen_port();
[479]250                       
[480]251                        if (port < range.first || port > range.second)
[746]252                                return session_->listen_on(range);     
[480]253                        else
254                        {
255                                signals.successful_listen();
256                               
257                                return true;
258                        }
[479]259                }
260               
[480]261                }
262                catch (const std::exception& e)
[479]263                {
[745]264                        event_log().post(shared_ptr<EventDetail>(
[754]265                                new EventStdException(event_logger::fatal, e, L"From bit::listen_on.")));
[479]266
[480]267                        return false;
[479]268                }
[660]269                catch (...)
[479]270                {
[480]271                        return false;
[479]272                }
[480]273        }
274
[482]275        int is_listening_on() 
[480]276        {
[746]277                if (!session_->is_listening())
[480]278                        return -1;     
279                else
[746]280                        return session_->listen_port();
[480]281        }
282
[482]283        void stop_listening()
[480]284        {
[482]285                ensure_dht_off();
[746]286                session_->listen_on(std::make_pair(0, 0));
[480]287        }
288
[541]289        bool ensure_dht_on(const dht_settings& dht)
290        {               
291                libt::dht_settings settings;
292                settings.max_peers_reply = dht.max_peers_reply;
293                settings.search_branching = dht.search_branching;
294                settings.service_port = dht.service_port;
295                settings.max_fail_count = dht.max_fail_count;
296               
[633]297                HAL_DEV_MSG(hal::wform(L"Seleted DHT port = %1%") % settings.service_port);
298               
[541]299                if (dht_settings_ != settings)
300                {
301                        dht_settings_ = settings;
[746]302                        session_->set_dht_settings(dht_settings_);
[541]303                }
304
[480]305                if (!dht_on_)
306                {               
307                        try
308                        {
[746]309                        session_->start_dht(dht_state_);
[480]310                        dht_on_ = true;
311                        }
312                        catch(...)
313                        {}
[479]314                }
[480]315                        return dht_on_;
316        }
317
[482]318        void ensure_dht_off()
[480]319        {
320                if (dht_on_)
[479]321                {
[746]322                        session_->stop_dht();           
[480]323                        dht_on_ = false;
[479]324                }
[480]325        }
326
[542]327        void set_mapping(bool upnp, bool nat_pmp)
[480]328        {
[771]329                upnp = true;
330
[542]331                if (upnp)
[479]332                {
[745]333                        event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Starting UPnP mapping.")));
[618]334
[746]335                        upnp_ = session_->start_upnp();
[479]336                }
[480]337                else
[479]338                {
[745]339                        event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Stopping UPnP mapping.")));
[618]340
[746]341                        session_->stop_upnp();
[618]342                        upnp_ = NULL;
[542]343                }
344
345                if (nat_pmp)
346                {
[745]347                        event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Starting NAT-PMP mapping.")));
[618]348
[746]349                        natpmp_ = session_->start_natpmp();
[542]350                }
351                else
352                {
[745]353                        event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Stopping NAT-PMP mapping.")));
[618]354
[746]355                        session_->stop_natpmp();
[618]356                        natpmp_ = NULL;
[479]357                }
[480]358        }
359
[618]360        std::wstring upnp_router_model()
361        {
362                if (upnp_)
363                        return to_wstr_shim(upnp_->router_model());
364                else
365                        return L"UPnP not started";
366        }
367
[482]368        void set_timeouts(int peers, int tracker)
[480]369        {
[746]370                libt::session_settings settings = session_->settings();
[480]371                settings.peer_connect_timeout = peers;
372                settings.tracker_completion_timeout = tracker;
373
[746]374                session_->set_settings(settings);
[480]375
[745]376                event_log().post(shared_ptr<EventDetail>(new EventMsg(
[531]377                        hal::wform(L"Set Timeouts, peer %1%, tracker %2%.") % peers % tracker)));
[480]378        }
379
[625]380        cache_settings get_cache_settings()
381        {
[746]382                libt::session_settings settings = session_->settings();
[625]383                cache_settings cache;
384
385                cache.cache_size = settings.cache_size;
386                cache.cache_expiry = settings.cache_expiry;
387
388                return cache;
389        }
390
391        void set_cache_settings(const cache_settings& cache)
392        {
[746]393                libt::session_settings settings = session_->settings();
[625]394
395                settings.cache_size = cache.cache_size;
396                settings.cache_expiry = cache.cache_expiry;
397
[746]398                session_->set_settings(settings);
[625]399
[745]400                event_log().post(shared_ptr<EventDetail>(new EventMsg(
[625]401                        hal::wform(L"Set cache parameters, %1% size and %2% expiry.") 
402                                % settings.cache_size % settings.cache_expiry)));
403        }
404
[506]405        queue_settings get_queue_settings()
406        {               
[746]407                libt::session_settings settings = session_->settings();
[506]408                queue_settings queue;
409
410                queue.auto_manage_interval = settings.auto_manage_interval;
411                queue.active_downloads = settings.active_downloads;
412                queue.active_seeds = settings.active_seeds;
413                queue.seeds_hard_limit = settings.active_limit;
414                queue.seed_ratio_limit = settings.share_ratio_limit;
415                queue.seed_ratio_time_limit = settings.seed_time_ratio_limit;
416                queue.seed_time_limit = settings.seed_time_limit;
417                queue.dont_count_slow_torrents = settings.dont_count_slow_torrents;
418                queue.auto_scrape_min_interval = settings.auto_scrape_min_interval;
419                queue.auto_scrape_interval = settings.auto_scrape_interval;
420                queue.close_redundant_connections = settings.close_redundant_connections;
421
422                return queue;
423        }
424
425        void set_queue_settings(const queue_settings& queue)
426        {
[746]427                libt::session_settings settings = session_->settings();
[506]428
429                settings.auto_manage_interval = queue.auto_manage_interval;
430                settings.active_downloads = queue.active_downloads;
431                settings.active_seeds = queue.active_seeds;
432                settings.active_limit = queue.seeds_hard_limit;
433                settings.share_ratio_limit = queue.seed_ratio_limit;
434                settings.seed_time_ratio_limit = queue.seed_ratio_time_limit;
435                settings.seed_time_limit = queue.seed_time_limit;
436                settings.dont_count_slow_torrents = queue.dont_count_slow_torrents;
437                settings.auto_scrape_min_interval = queue.auto_scrape_min_interval;
438                settings.auto_scrape_interval = queue.auto_scrape_interval;
439                settings.close_redundant_connections = queue.close_redundant_connections;
440
[746]441                session_->set_settings(settings);
[506]442
[745]443                event_log().post(shared_ptr<EventDetail>(new EventMsg(
[531]444                        hal::wform(L"Set queue parameters, %1% downloads and %2% active seeds.") 
[506]445                                % settings.active_downloads % settings.active_seeds)));
446        }
447
[517]448        timeouts get_timeouts()
449        {               
[746]450                libt::session_settings settings = session_->settings();
[517]451                timeouts times;
452
453                times.tracker_completion_timeout = settings.tracker_completion_timeout;
454                times.tracker_receive_timeout = settings.tracker_receive_timeout;
455                times.stop_tracker_timeout = settings.stop_tracker_timeout;
456
457                times.request_queue_time = settings.request_queue_time;
458                times.piece_timeout = settings.piece_timeout;
459                times.min_reconnect_time = settings.min_reconnect_time;         
460
461                times.peer_timeout = settings.peer_timeout;
462                times.urlseed_timeout = settings.urlseed_timeout;
463                times.peer_connect_timeout = settings.peer_connect_timeout;
464                times.inactivity_timeout = settings.inactivity_timeout;
465                times.handshake_timeout = settings.handshake_timeout;
466
467                return times;
468        }
469
470        void set_timeouts(const timeouts& times)
471        {
[746]472                libt::session_settings settings = session_->settings();
[517]473
474                settings.tracker_completion_timeout = times.tracker_completion_timeout;
475                settings.tracker_receive_timeout = times.tracker_receive_timeout;
476                settings.stop_tracker_timeout = times.stop_tracker_timeout;
477
478                settings.request_queue_time = times.request_queue_time;
479                settings.piece_timeout = times.piece_timeout;
480                settings.min_reconnect_time = times.min_reconnect_time;         
481
482                settings.peer_timeout = times.peer_timeout;
483                settings.urlseed_timeout = times.urlseed_timeout;
484                settings.peer_connect_timeout = times.peer_connect_timeout;
485                settings.inactivity_timeout = times.inactivity_timeout;
486                settings.handshake_timeout = times.handshake_timeout;
487
[746]488                session_->set_settings(settings);
[517]489
[745]490                event_log().post(shared_ptr<EventDetail>(new EventMsg(
[531]491                        hal::wform(L"Set timeouts, peers- %1% secs, tracker- %2% secs.") 
[517]492                                % settings.peer_timeout % settings.tracker_receive_timeout)));
493        }
494
[482]495        void set_session_limits(int maxConn, int maxUpload)
[480]496        {               
[746]497                session_->set_max_uploads(maxUpload);
498                session_->set_max_connections(maxConn);
[479]499               
[745]500                event_log().post(shared_ptr<EventDetail>(new EventMsg(
[531]501                        hal::wform(L"Set connections totals %1% and uploads %2%.") 
[480]502                                % maxConn % maxUpload)));
503        }
504
[482]505        void set_session_speed(float download, float upload)
[480]506        {
507                int down = (download > 0) ? static_cast<int>(download*1024) : -1;
[746]508                session_->set_download_rate_limit(down);
[480]509                int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
[746]510                session_->set_upload_rate_limit(up);
[480]511               
[745]512                event_log().post(shared_ptr<EventDetail>(new EventMsg(
[531]513                        hal::wform(L"Set session rates at download %1% and upload %2%.") 
[746]514                                % session_->download_rate_limit() % session_->upload_rate_limit())));
[480]515        }
516
[624]517        cache_details get_cache_details() const
518        {
[746]519                libt::cache_status cs = session_->get_cache_status();
[624]520
521                return cache_details(cs.blocks_written, cs.writes, 
522                        cs.blocks_read, cs.blocks_read_hit, cs.reads,
523                        cs.cache_size, cs.read_cache_size);
524        }
525
[482]526        bool ensure_ip_filter_on(progress_callback fn)
[480]527        {
528                try
[479]529                {
530               
[480]531                if (!ip_filter_loaded_)
[479]532                {
[480]533                        ip_filter_load(fn);
534                        ip_filter_loaded_ = true;
[479]535                }
536               
[480]537                if (!ip_filter_on_)
[479]538                {
[746]539                        session_->set_ip_filter(ip_filter_);
[480]540                        ip_filter_on_ = true;
541                        ip_filter_count();
[479]542                }
543               
544                }
[480]545                catch(const std::exception& e)
546                {               
[745]547                        hal::event_log().post(boost::shared_ptr<hal::EventDetail>(
[754]548                                new hal::EventStdException(event_logger::critical, e, L"ensure_ip_filter_on"))); 
[480]549
[482]550                        ensure_ip_filter_off();
[480]551                }
552
[745]553                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"IP filters on.")));     
[480]554
555                return false;
556        }
557
[482]558        void ensure_ip_filter_off()
[480]559        {
[746]560                session_->set_ip_filter(libt::ip_filter());
[480]561                ip_filter_on_ = false;
[479]562               
[745]563                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"IP filters off.")));   
[480]564        }
565
[681]566#       ifndef TORRENT_DISABLE_ENCRYPTION       
[541]567        void ensure_pe_on(const pe_settings& pe_s)
[480]568        {
569                libt::pe_settings pe;
570               
[541]571                switch (pe_s.encrypt_level)
[479]572                {
[480]573                        case 0:
574                                pe.allowed_enc_level = libt::pe_settings::plaintext;
575                                break;
576                        case 1:
577                                pe.allowed_enc_level = libt::pe_settings::rc4;
578                                break;
579                        case 2:
580                                pe.allowed_enc_level = libt::pe_settings::both;
581                                break;
582                        default:
583                                pe.allowed_enc_level = libt::pe_settings::both;
584                               
[745]585                                hal::event_log().post(shared_ptr<hal::EventDetail>(
[480]586                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
[541]587                                                (hal::wform(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % pe_s.encrypt_level).str())));
[479]588                }
[480]589
[541]590                switch (pe_s.conn_in_policy)
[479]591                {
[480]592                        case 0:
593                                pe.in_enc_policy = libt::pe_settings::forced;
594                                break;
595                        case 1:
596                                pe.in_enc_policy = libt::pe_settings::enabled;
597                                break;
598                        case 2:
599                                pe.in_enc_policy = libt::pe_settings::disabled;
600                                break;
601                        default:
602                                pe.in_enc_policy = libt::pe_settings::enabled;
603                               
[745]604                                hal::event_log().post(shared_ptr<hal::EventDetail>(
[480]605                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
[541]606                                                (hal::wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % pe_s.conn_in_policy).str())));
[479]607                }
[480]608
[541]609                switch (pe_s.conn_out_policy)
[479]610                {
[480]611                        case 0:
612                                pe.out_enc_policy = libt::pe_settings::forced;
613                                break;
614                        case 1:
615                                pe.out_enc_policy = libt::pe_settings::enabled;
616                                break;
617                        case 2:
618                                pe.out_enc_policy = libt::pe_settings::disabled;
619                                break;
620                        default:
621                                pe.out_enc_policy = libt::pe_settings::enabled;
622                               
[745]623                                hal::event_log().post(shared_ptr<hal::EventDetail>(
[480]624                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
[541]625                                                (hal::wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % pe_s.conn_out_policy).str())));
[479]626                }
627               
[541]628                pe.prefer_rc4 = pe_s.prefer_rc4;
[480]629               
630                try
[479]631                {
632               
[746]633                session_->set_pe_settings(pe);
[480]634               
[479]635                }
[480]636                catch(const std::exception& e)
[479]637                {
[745]638                        hal::event_log().post(boost::shared_ptr<hal::EventDetail>(
[754]639                                        new hal::EventStdException(event_logger::critical, e, L"ensure_pe_on"))); 
[480]640                                       
[482]641                        ensure_pe_off();               
[479]642                }
643               
[745]644                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption on.")));
[480]645        }
646
[482]647        void ensure_pe_off()
[480]648        {
649                libt::pe_settings pe;
650                pe.out_enc_policy = libt::pe_settings::disabled;
651                pe.in_enc_policy = libt::pe_settings::disabled;
[479]652               
[480]653                pe.allowed_enc_level = libt::pe_settings::both;
654                pe.prefer_rc4 = true;
[479]655               
[746]656                session_->set_pe_settings(pe);
[480]657
[745]658                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption off.")));
[479]659        }
[681]660#       endif
[641]661       
662        void set_resolve_countries(bool b)
663        {               
[642]664                resolve_countries_ = b;
665
[660]666                for (torrent_manager::torrent_by_name::iterator i=the_torrents_.begin(), e=the_torrents_.end(); 
[641]667                        i != e; ++i)
668                {
[642]669                        (*i).torrent->set_resolve_countries(resolve_countries_);
[641]670                }
[480]671
[641]672                if (b)                 
[745]673                        event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Set to resolve countries.")));
[641]674                else                   
[745]675                        event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Not resolving countries.")));
[641]676        }
677
678        void start_smart_ban_plugin()
679        {
[746]680                session_->add_extension(&libt::create_smart_ban_plugin);
[745]681                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Started smart ban plugin.")));
[641]682        }
683
684        void start_ut_pex_plugin()
685        {
[746]686                session_->add_extension(&libt::create_ut_pex_plugin);
[745]687                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Started uTorrent peer exchange plugin.")));
[641]688        }
689
690        void start_ut_metadata_plugin()
691        {
[746]692                session_->add_extension(&libt::create_ut_metadata_plugin);
[745]693                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Started uTorrent metadata plugin.")));
[641]694        }
695
696        void start_metadata_plugin()
697        {
[746]698                session_->add_extension(&libt::create_metadata_plugin);
[745]699                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Started metadata plugin.")));
[641]700        }
701
[554]702        void ip_v4_filter_block(boost::asio::ip::address_v4 first, boost::asio::ip::address_v4 last)
[480]703        {
704                ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
705                ip_filter_count();
706                ip_filter_changed_ = true;
707        }
708
[554]709        void ip_v6_filter_block(boost::asio::ip::address_v6 first, boost::asio::ip::address_v6 last)
[480]710        {
711                ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
712                ip_filter_count();
713                ip_filter_changed_ = true;
714        }
715
716        size_t ip_filter_size()
717        {
718                return ip_filter_count_;
719        }
720
[482]721        void clear_ip_filter()
[480]722        {
723                ip_filter_ = libt::ip_filter();
[746]724                session_->set_ip_filter(libt::ip_filter());     
[480]725                ip_filter_changed_ = true;
726                ip_filter_count();
727        }
728
729        bool ip_filter_import_dat(boost::filesystem::path file, progress_callback fn, bool octalFix);
730
731        struct 
732        {
733                signaler<> successful_listen;
734                signaler<> torrent_finished;
[553]735
736                boost::signal<bool()> torrent_paused;
[480]737        } 
738        signals;
739
[503]740        void start_alert_handler();
[482]741        void stop_alert_handler();
742        void alert_handler();
[481]743
[764]744        void add_torrent(wpath file, wpath saveDirectory, bool start_stopped, bool managed, bit::allocations alloc, 
[739]745                        boost::filesystem::wpath moveToDirectory) 
[481]746        {
747                try 
748                {       
[739]749//              torrent_internal_ptr TIp;
[481]750
751                std::pair<std::string, std::string> names = extract_names(file);
752                wstring xml_name = from_utf8(names.first) + L".xml";
753
[739]754/*              if (false && fs::exists(file.parent_path()/xml_name))
[481]755                {
756                        torrent_standalone tsa;
757                       
[552]758                        if (tsa.load_standalone(file.parent_path()/xml_name))
[481]759                        {
760                                TIp = tsa.torrent;
761                               
762                                TIp->set_save_directory(saveDirectory, true);                   
763                                if (useMoveTo)
764                                        TIp->set_move_to_directory(moveToDirectory);
765
766                                TIp->prepare(file);
767                        }
768                }
[739]769*/
770                torrent_internal_ptr TIp =
771                        the_torrents_.create_torrent(file, saveDirectory, alloc, moveToDirectory);
[481]772
[739]773                if(TIp)
[481]774                {
[614]775                        TIp->set_managed(managed);
[748]776                        TIp->set_transfer_speed(bittorrent::Instance().default_torrent_download(), 
777                                bittorrent::Instance().default_torrent_upload());
778                        TIp->set_connection_limit(bittorrent::Instance().default_torrent_max_connections(), 
779                                bittorrent::Instance().default_torrent_max_uploads());
[642]780                        TIp->set_resolve_countries(resolve_countries_);
[739]781
[748]782                        TIp->start();
[764]783
784                        if (!start_stopped) TIp->resume();
[481]785                }
786               
787                }
788                catch (const std::exception& e)
789                {
[745]790                        event_log().post(shared_ptr<EventDetail>(
[481]791                                new EventTorrentException(event_logger::critical, event_logger::torrentException, 
792                                        std::string(e.what()), to_utf8(file.string()), std::string("addTorrent"))));
793                }
794        }
795
[741]796        void remove_torrent(const wstring& name)
[482]797        {
798                try {
[745]799                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Removing Torrent.")));
[739]800
801                boost::shared_ptr<file_details_vec> files = boost::shared_ptr<file_details_vec>(new file_details_vec());               
[741]802                torrent_internal_ptr pTI = the_torrents_.get(name);
[739]803
[741]804                the_torrents_.remove_torrent(name);
[482]805               
[745]806                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Removed")));
[482]807               
[741]808                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(name, "remove_torrent")
[482]809        }
810
[741]811        void remove_torrent_wipe_files(const std::wstring& name, remove_files fn)
[482]812        {
813                try {
[745]814                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Removing Torrent and files.")));
[739]815
816                boost::shared_ptr<file_details_vec> files = boost::shared_ptr<file_details_vec>(new file_details_vec());               
[741]817                torrent_internal_ptr pTI = the_torrents_.get(name);
[739]818
819                pTI->get_file_details(*files);
820                thread_t t(bind(fn, pTI->get_save_directory(), files));
821
822                pTI->clear_resume_data();
823                pTI->delete_torrent_file();
824
[741]825                the_torrents_.remove_torrent(name);
[482]826               
[745]827                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Removed, started thread.")));
[482]828               
[741]829                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(name, "remove_torrent_wipe_files")
[482]830        }
831
832        void resume_all()
833        {
834                try {
[481]835                       
[749]836                event_log().post(shared_ptr<EventDetail>(new EventMsg(L"Resuming all torrents.")));
[481]837               
[660]838                for (torrent_manager::torrent_by_name::iterator i=the_torrents_.begin(), e=the_torrents_.end(); i != e;)
[481]839                {
[569]840                        wpath file = wpath(hal::app().get_working_directory())/L"torrents"/(*i).torrent->filename();
[481]841                       
842                        if (exists(file))
843                        {               
844                                try 
845                                {
846                                       
847                                (*i).torrent->prepare(file);   
[749]848                                (*i).torrent->start(); 
[481]849                               
850                                ++i;
851                               
852                                }
853                                catch(const libt::duplicate_torrent&)
854                                {
[745]855                                        hal::event_log().post(shared_ptr<hal::EventDetail>(
[481]856                                                new hal::EventDebug(hal::event_logger::debug, L"Encountered duplicate torrent")));
857                                       
858                                        ++i; // Harmless, don't worry about it.
859                                }
860                                catch(const std::exception& e) 
861                                {
[745]862                                        hal::event_log().post(shared_ptr<hal::EventDetail>(
[681]863                                                new hal::EventStdException(hal::event_logger::warning, e, L"resume_all")));
[481]864                                       
[482]865                                        the_torrents_.erase(i++);
[481]866                                }                       
867                        }
868                        else
869                        {
[482]870                                the_torrents_.erase(i++);
[481]871                        }
872                }
873               
[681]874                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "resume_all")
[481]875        }
876
[681]877        bool close_counter(int* count)
878        {
879                --(*count);
880                return true;
881        }
882       
[482]883        void close_all(boost::optional<report_num_active> fn)
[481]884        {
885                try 
886                {       
[681]887
[754]888                event_log().post(shared_ptr<EventDetail>(new EventInfo(L"Saving torrent data ...")));
[481]889
[482]890                save_torrent_data();
[481]891
[754]892                event_log().post(shared_ptr<EventDetail>(new EventInfo(L"       ... stopping all torrents")));
[681]893
[746]894                session_->pause();             
[681]895
[690]896                // Ok this polling loop here is a bit curde, but a blocking wait is actually appropiate.               
897                { 
898                int num_active = 1;
[681]899
[690]900                while (num_active > 0)
901                {
902                        num_active = 0;
[681]903
[690]904                        for (torrent_manager::torrent_by_name::iterator i=the_torrents_.begin(), e=the_torrents_.end(); 
905                                        i != e; ++i)
906                        {
[748]907                                if (    (*i).torrent
908                                        && 
909                                        (*i).torrent->state() != torrent_details::torrent_in_error
910                                        && 
911                                        (       (       (*i).torrent->state() != torrent_details::torrent_stopped
912                                                        && 
913                                                        (*i).torrent->state() != torrent_details::torrent_paused
914                                                )
915                                                || 
916                                                (*i).torrent->awaiting_resume_data()
917                                        )
918                                )
[690]919                                {
[706]920#                                       ifdef HAL_TORRENT_DEV_MSGES
921                                                (*i).torrent->output_torrent_debug_details();
922#                                       endif
[690]923                                        num_active += 1;
924                                }
[681]925                        }
926
[754]927                        event_log().post(shared_ptr<EventDetail>(new EventInfo(hal::wform(L"    ... %1% still active") % (num_active))));
[681]928
[691]929                        if (fn) (*fn)(num_active);
[632]930                        boost::this_thread::sleep(pt::milliseconds(500));
[690]931                } 
932               
[481]933                }
934               
[754]935                event_log().post(shared_ptr<EventDetail>(new EventInfo(L"       ... all torrents stopped.")));         
[481]936               
[681]937                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "close_all()")
[481]938        }
[479]939       
[482]940        void save_torrent_data()
[479]941        {       
942                mutex_t::scoped_lock l(mutex_);
943                try
944                {
945               
[491]946                the_torrents_.save_to_ini();
[696]947                bittorrent_ini_.save_data();
[479]948                       
949                if (dht_on_) 
950                {       
[746]951                        halencode(hal::app().get_working_directory()/L"DHTState.bin", session_->dht_state());
[479]952                }
953               
954                }               
955                catch(std::exception& e)
956                {
[745]957                        event_log().post(shared_ptr<EventDetail>(\
[681]958                                new EventStdException(event_logger::critical, e, L"save_torrent_data()")));
[479]959                }
960        }
961       
[642]962        int default_torrent_max_connections() { return default_torrent_max_connections_; }
963        int default_torrent_max_uploads() { return default_torrent_max_uploads_; }
964        float default_torrent_download() { return default_torrent_download_; }
965        float default_torrent_upload() { return default_torrent_upload_; }
[479]966       
967private:
[508]968        bool create_torrent(const create_torrent_params& params, fs::wpath out_file, progress_callback fn);
[759]969
970        void service_thread(size_t);
[764]971        void alert_handler_wait(const boost::system::error_code&);
[759]972
[760]973        void execute_action(const boost::system::error_code&, bit::timeout_actions action);
974        void execute_callback(const boost::system::error_code&, action_callback_t action);
[759]975
976        void acquire_work_object()
977        {
978                HAL_DEV_MSG(hal::wform(L"Acquiring service work object."));
979
980                work_.reset(new boost::asio::io_service::work(io_service_));
981        }
982
983        void discard_work_object()
984        {
985                work_.reset();
986
987                HAL_DEV_MSG(hal::wform(L"Discarded service work object"));
988        }
[760]989
990        void schedual_action(boost::posix_time::ptime time, bit::timeout_actions action);
991        void schedual_action(boost::posix_time::time_duration duration, bit::timeout_actions action);
992        void schedual_callback(boost::posix_time::ptime time, action_callback_t action);
993        void schedual_callback(boost::posix_time::time_duration duration, action_callback_t action);   
[764]994        void schedual_cancel();
[479]995       
[746]996        boost::optional<libt::session> session_;       
[780]997        SessionDetail session_details_;
998
[479]999        mutable mutex_t mutex_;
[760]1000       
1001        ini_file bittorrent_ini_;
1002        torrent_manager the_torrents_; 
[479]1003
[760]1004        boost::asio::io_service io_service_;
1005        std::auto_ptr<boost::asio::io_service::work> work_;
1006
1007        boost::asio::deadline_timer action_timer_;
1008
[761]1009        boost::asio::deadline_timer alert_timer_;
1010        bool keep_checking_;
1011
[759]1012        typedef boost::shared_ptr<thread_t> shared_thread_ptr;
1013
1014        std::vector<shared_thread_ptr> service_threads_;
[479]1015       
[642]1016        int default_torrent_max_connections_;
1017        int default_torrent_max_uploads_;
1018        float default_torrent_download_;
1019        float default_torrent_upload_;
[479]1020       
[642]1021        bool resolve_countries_;
[479]1022        bool ip_filter_on_;
1023        bool ip_filter_loaded_;
1024        bool ip_filter_changed_;
1025        libt::ip_filter ip_filter_;
1026        size_t ip_filter_count_;
1027       
1028        void ip_filter_count();
1029        void ip_filter_load(progress_callback fn);
[554]1030        void ip_filter_import(std::vector<libt::ip_range<boost::asio::ip::address_v4> >& v4,
1031                std::vector<libt::ip_range<boost::asio::ip::address_v6> >& v6);
[479]1032       
1033        bool dht_on_;
1034        libt::dht_settings dht_settings_;
[508]1035        libt::entry dht_state_; 
[618]1036
1037        libt::upnp* upnp_;
1038        libt::natpmp* natpmp_;
[479]1039};
1040
1041}
[746]1042
1043#include "halSessionStates.hpp"
Note: See TracBrowser for help on using the repository browser.