source: trunk/src/halSession.hpp @ 739

Revision 739, 33.4 KB checked in by Eoin, 11 years ago (diff)

Cleaning up torrent removal code.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2009.
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
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>
26#       include <libtorrent/upnp.hpp>
27#       include <libtorrent/natpmp.hpp>
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>
34#       include <libtorrent/extensions/ut_metadata.hpp>
35#       include <libtorrent/extensions/smart_ban.hpp>
36#pragma warning (pop)
37
38#include "halIni.hpp"
39#include "halTypes.hpp"
40#include "halEvent.hpp"
41#include "halConfig.hpp"
42#include "halTorrentInternal.hpp"
43#include "halSignaler.hpp"
44
45namespace boost {
46namespace serialization {
47
48template<class Archive, class address_type>
49void save(Archive& ar, const address_type& ip, const unsigned int version)
50{       
51        unsigned long addr = ip.to_ulong();     
52        ar & BOOST_SERIALIZATION_NVP(addr);
53}
54
55template<class Archive, class address_type>
56void load(Archive& ar, address_type& ip, const unsigned int version)
57{       
58        unsigned long addr;
59        ar & BOOST_SERIALIZATION_NVP(addr);     
60        ip = address_type(addr);
61}
62
63template<class Archive, class String, class Traits>
64void save(Archive& ar, const boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
65{       
66        String str = p.string();
67        ar & BOOST_SERIALIZATION_NVP(str);
68}
69
70template<class Archive, class String, class Traits>
71void load(Archive& ar, boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
72{       
73        String str;
74        ar & BOOST_SERIALIZATION_NVP(str);
75
76        p = str;
77}
78
79template<class Archive, class String, class Traits>
80inline void serialize(
81        Archive & ar,
82        boost::filesystem::basic_path<String, Traits>& p,
83        const unsigned int file_version)
84{
85        split_free(ar, p, file_version);           
86}
87
88template<class Archive, class address_type>
89void serialize(Archive& ar, libtorrent::ip_range<address_type>& addr, const unsigned int version)
90{       
91        ar & BOOST_SERIALIZATION_NVP(addr.first);
92        ar & BOOST_SERIALIZATION_NVP(addr.last);
93        addr.flags = libtorrent::ip_filter::blocked;
94}
95
96template<class Archive>
97void serialize(Archive& ar, hal::tracker_detail& tracker, const unsigned int version)
98{       
99        ar & BOOST_SERIALIZATION_NVP(tracker.url);
100        ar & BOOST_SERIALIZATION_NVP(tracker.tier);
101}
102
103} // namespace serialization
104} // namespace boost
105
106BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v4)
107BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v6)
108
109namespace libtorrent
110{
111
112template<class Addr>
113bool operator==(const libtorrent::ip_range<Addr>& lhs, const int flags)
114{
115        return (lhs.flags == flags);
116}
117
118inline
119std::ostream& operator<<(std::ostream& os, libtorrent::ip_range<asio::ip::address_v4>& ip)
120{
121        os << ip.first.to_ulong();
122        os << ip.last.to_ulong();
123       
124        return os;
125}
126
127} // namespace libtorrent
128
129namespace hal
130{
131
132namespace libt = libtorrent;
133
134inline
135bool operator!=(const libt::dht_settings& lhs, const libt::dht_settings& rhs)
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
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
225#define HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH(FUNCTION) \
226catch (const libt::invalid_handle&) \
227{\
228        event_log.post(shared_ptr<EventDetail>( \
229                new EventInvalidTorrent(event_logger::info, event_logger::invalid_torrent, name, std::string(FUNCTION)))); \
230}\
231catch (const invalid_torrent& t) \
232{ \
233        event_log.post(shared_ptr<EventDetail>( \
234                new EventInvalidTorrent(event_logger::info, event_logger::invalid_torrent, t.who(), std::string(FUNCTION)))); \
235} \
236catch (const access_violation& e) \
237{ \
238        hal::event_log.post(shared_ptr<hal::EventDetail>( \
239                new hal::EventMsg(hal::wform(L"Torrent property %1% access_violation (code %2$x) at %3$x. Bad address %4$x") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % (unsigned)e.badAddress(), \
240                        hal::event_logger::critical))); \
241} \
242catch (const win32_exception& e) \
243{ \
244        hal::event_log.post(shared_ptr<hal::EventDetail>( \
245                new hal::EventMsg(hal::wform(L"Torrent property %1% win32_exception (code %2$x) at %3$x") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where(), \
246                        hal::event_logger::critical))); \
247} \
248catch (const std::exception& e) \
249{ \
250        event_log.post(shared_ptr<EventDetail>( \
251                new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), name, std::string(FUNCTION)))); \
252} \
253catch(...) \
254{ \
255        hal::event_log.post(shared_ptr<hal::EventDetail>( \
256                new hal::EventMsg(hal::wform(L"%1% catch all") % hal::from_utf8(FUNCTION), \
257                        hal::event_logger::critical))); \
258}
259
260#define HAL_GENERIC_TORRENT_EXCEPTION_CATCH(TORRENT, FUNCTION) \
261catch (const libt::invalid_handle&) \
262{\
263        event_log.post(shared_ptr<EventDetail>( \
264                new EventInvalidTorrent(event_logger::info, event_logger::invalid_torrent, TORRENT, std::string(FUNCTION)))); \
265}\
266catch (const invalid_torrent& t) \
267{\
268        event_log.post(shared_ptr<EventDetail>( \
269                new EventInvalidTorrent(event_logger::info, event_logger::invalid_torrent, t.who(), std::string(FUNCTION)))); \
270}\
271catch (const access_violation& e) \
272{ \
273        hal::event_log.post(shared_ptr<hal::EventDetail>( \
274                new hal::EventMsg(hal::wform(L"Generic Torrent %1% access_violation (code %2$x) at %3$x. Bad address %4$x (%5%)") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % (unsigned)e.badAddress() % TORRENT, \
275                        hal::event_logger::critical))); \
276} \
277catch (const win32_exception& e) \
278{ \
279        hal::event_log.post(shared_ptr<hal::EventDetail>( \
280                new hal::EventMsg(hal::wform(L"Generic Torrent %1% win32_exception (code %2$x) at %3$x (%4%)") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % TORRENT, \
281                        hal::event_logger::critical))); \
282} \
283catch (const std::exception& e) \
284{ \
285        event_log.post(shared_ptr<EventDetail>( \
286                new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), TORRENT, std::string(FUNCTION)))); \
287} \
288catch (...) \
289{ \
290        hal::event_log.post(shared_ptr<hal::EventDetail>( \
291                new hal::EventMsg(hal::wform(L"Generic Torrent %1% catch all") % hal::from_utf8(FUNCTION), \
292                        hal::event_logger::critical))); \
293}
294
295#define HAL_GENERIC_PIMPL_EXCEPTION_CATCH(FUNCTION) \
296catch (const access_violation& e) \
297{ \
298        hal::event_log.post(shared_ptr<hal::EventDetail>( \
299                new hal::EventMsg(hal::wform(L"Generic Session Pimpl %1% access_violation (code %2$x) at %3$x. Bad address %4$x") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % (unsigned)e.badAddress(), \
300                        hal::event_logger::critical))); \
301} \
302catch (const win32_exception& e) \
303{ \
304        hal::event_log.post(shared_ptr<hal::EventDetail>( \
305                new hal::EventMsg(hal::wform(L"Generic Session Pimpl %1% win32_exception (code %2$x) at %3$x") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where(), \
306                        hal::event_logger::critical))); \
307} \
308catch (const std::exception& e) \
309{ \
310        hal::event_log.post(shared_ptr<hal::EventDetail>( \
311        new hal::EventMsg(hal::wform(L"Generic Session Pimpl %1% std_exception: %2%") % hal::from_utf8(FUNCTION) % hal::from_utf8(e.what()), \
312                        hal::event_logger::critical))); \
313} \
314catch (...) \
315{ \
316        hal::event_log.post(shared_ptr<hal::EventDetail>( \
317                new hal::EventMsg(hal::wform(L"Generic Session Pimpl %1% catch all") % hal::from_utf8(FUNCTION), \
318                        hal::event_logger::critical))); \
319}
320
321class bit_impl
322{
323        friend class bit;
324
325private:
326        bit_impl();     
327public: 
328        ~bit_impl();
329
330        bool listen_on(std::pair<int, int> const& range)
331        {
332                try
333                {
334               
335                if (!session_.is_listening())
336                {
337                        return session_.listen_on(range);
338                }
339                else
340                {
341                        int port = session_.listen_port();
342                       
343                        if (port < range.first || port > range.second)
344                                return session_.listen_on(range);       
345                        else
346                        {
347                                signals.successful_listen();
348                               
349                                return true;
350                        }
351                }
352               
353                }
354                catch (const std::exception& e)
355                {
356                        event_log.post(shared_ptr<EventDetail>(
357                                new EventStdException(event_logger::fatal, e, L"From bit::listenOn.")));
358
359                        return false;
360                }
361                catch (...)
362                {
363                        return false;
364                }
365        }
366
367        int is_listening_on() 
368        {
369                if (!session_.is_listening())
370                        return -1;     
371                else
372                        return session_.listen_port();
373        }
374
375        void stop_listening()
376        {
377                ensure_dht_off();
378                session_.listen_on(std::make_pair(0, 0));
379        }
380
381        bool ensure_dht_on(const dht_settings& dht)
382        {               
383                libt::dht_settings settings;
384                settings.max_peers_reply = dht.max_peers_reply;
385                settings.search_branching = dht.search_branching;
386                settings.service_port = dht.service_port;
387                settings.max_fail_count = dht.max_fail_count;
388               
389                HAL_DEV_MSG(hal::wform(L"Seleted DHT port = %1%") % settings.service_port);
390               
391                if (dht_settings_ != settings)
392                {
393                        dht_settings_ = settings;
394                        session_.set_dht_settings(dht_settings_);
395                }
396
397                if (!dht_on_)
398                {               
399                        try
400                        {
401                        session_.start_dht(dht_state_);
402                        dht_on_ = true;
403                        }
404                        catch(...)
405                        {}
406                }
407                        return dht_on_;
408        }
409
410        void ensure_dht_off()
411        {
412                if (dht_on_)
413                {
414                        session_.stop_dht();           
415                        dht_on_ = false;
416                }
417        }
418
419        void set_mapping(bool upnp, bool nat_pmp)
420        {
421                if (upnp)
422                {
423                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting UPnP mapping.")));
424
425                        upnp_ = session_.start_upnp();
426                }
427                else
428                {
429                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Stopping UPnP mapping.")));
430
431                        session_.stop_upnp();
432                        upnp_ = NULL;
433                }
434
435                if (nat_pmp)
436                {
437                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting NAT-PMP mapping.")));
438
439                        natpmp_ = session_.start_natpmp();
440                }
441                else
442                {
443                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Stopping NAT-PMP mapping.")));
444
445                        session_.stop_natpmp();
446                        natpmp_ = NULL;
447                }
448        }
449
450        std::wstring upnp_router_model()
451        {
452                if (upnp_)
453                        return to_wstr_shim(upnp_->router_model());
454                else
455                        return L"UPnP not started";
456        }
457
458        void set_timeouts(int peers, int tracker)
459        {
460                libt::session_settings settings = session_.settings();
461                settings.peer_connect_timeout = peers;
462                settings.tracker_completion_timeout = tracker;
463
464                session_.set_settings(settings);
465
466                event_log.post(shared_ptr<EventDetail>(new EventMsg(
467                        hal::wform(L"Set Timeouts, peer %1%, tracker %2%.") % peers % tracker)));
468        }
469
470        cache_settings get_cache_settings()
471        {
472                libt::session_settings settings = session_.settings();
473                cache_settings cache;
474
475                cache.cache_size = settings.cache_size;
476                cache.cache_expiry = settings.cache_expiry;
477
478                return cache;
479        }
480
481        void set_cache_settings(const cache_settings& cache)
482        {
483                libt::session_settings settings = session_.settings();
484
485                settings.cache_size = cache.cache_size;
486                settings.cache_expiry = cache.cache_expiry;
487
488                session_.set_settings(settings);
489
490                event_log.post(shared_ptr<EventDetail>(new EventMsg(
491                        hal::wform(L"Set cache parameters, %1% size and %2% expiry.") 
492                                % settings.cache_size % settings.cache_expiry)));
493        }
494
495        queue_settings get_queue_settings()
496        {               
497                libt::session_settings settings = session_.settings();
498                queue_settings queue;
499
500                queue.auto_manage_interval = settings.auto_manage_interval;
501                queue.active_downloads = settings.active_downloads;
502                queue.active_seeds = settings.active_seeds;
503                queue.seeds_hard_limit = settings.active_limit;
504                queue.seed_ratio_limit = settings.share_ratio_limit;
505                queue.seed_ratio_time_limit = settings.seed_time_ratio_limit;
506                queue.seed_time_limit = settings.seed_time_limit;
507                queue.dont_count_slow_torrents = settings.dont_count_slow_torrents;
508                queue.auto_scrape_min_interval = settings.auto_scrape_min_interval;
509                queue.auto_scrape_interval = settings.auto_scrape_interval;
510                queue.close_redundant_connections = settings.close_redundant_connections;
511
512                return queue;
513        }
514
515        void set_queue_settings(const queue_settings& queue)
516        {
517                libt::session_settings settings = session_.settings();
518
519                settings.auto_manage_interval = queue.auto_manage_interval;
520                settings.active_downloads = queue.active_downloads;
521                settings.active_seeds = queue.active_seeds;
522                settings.active_limit = queue.seeds_hard_limit;
523                settings.share_ratio_limit = queue.seed_ratio_limit;
524                settings.seed_time_ratio_limit = queue.seed_ratio_time_limit;
525                settings.seed_time_limit = queue.seed_time_limit;
526                settings.dont_count_slow_torrents = queue.dont_count_slow_torrents;
527                settings.auto_scrape_min_interval = queue.auto_scrape_min_interval;
528                settings.auto_scrape_interval = queue.auto_scrape_interval;
529                settings.close_redundant_connections = queue.close_redundant_connections;
530
531                session_.set_settings(settings);
532
533                event_log.post(shared_ptr<EventDetail>(new EventMsg(
534                        hal::wform(L"Set queue parameters, %1% downloads and %2% active seeds.") 
535                                % settings.active_downloads % settings.active_seeds)));
536        }
537
538        timeouts get_timeouts()
539        {               
540                libt::session_settings settings = session_.settings();
541                timeouts times;
542
543                times.tracker_completion_timeout = settings.tracker_completion_timeout;
544                times.tracker_receive_timeout = settings.tracker_receive_timeout;
545                times.stop_tracker_timeout = settings.stop_tracker_timeout;
546
547                times.request_queue_time = settings.request_queue_time;
548                times.piece_timeout = settings.piece_timeout;
549                times.min_reconnect_time = settings.min_reconnect_time;         
550
551                times.peer_timeout = settings.peer_timeout;
552                times.urlseed_timeout = settings.urlseed_timeout;
553                times.peer_connect_timeout = settings.peer_connect_timeout;
554                times.inactivity_timeout = settings.inactivity_timeout;
555                times.handshake_timeout = settings.handshake_timeout;
556
557                return times;
558        }
559
560        void set_timeouts(const timeouts& times)
561        {
562                libt::session_settings settings = session_.settings();
563
564                settings.tracker_completion_timeout = times.tracker_completion_timeout;
565                settings.tracker_receive_timeout = times.tracker_receive_timeout;
566                settings.stop_tracker_timeout = times.stop_tracker_timeout;
567
568                settings.request_queue_time = times.request_queue_time;
569                settings.piece_timeout = times.piece_timeout;
570                settings.min_reconnect_time = times.min_reconnect_time;         
571
572                settings.peer_timeout = times.peer_timeout;
573                settings.urlseed_timeout = times.urlseed_timeout;
574                settings.peer_connect_timeout = times.peer_connect_timeout;
575                settings.inactivity_timeout = times.inactivity_timeout;
576                settings.handshake_timeout = times.handshake_timeout;
577
578                session_.set_settings(settings);
579
580                event_log.post(shared_ptr<EventDetail>(new EventMsg(
581                        hal::wform(L"Set timeouts, peers- %1% secs, tracker- %2% secs.") 
582                                % settings.peer_timeout % settings.tracker_receive_timeout)));
583        }
584
585        void set_session_limits(int maxConn, int maxUpload)
586        {               
587                session_.set_max_uploads(maxUpload);
588                session_.set_max_connections(maxConn);
589               
590                event_log.post(shared_ptr<EventDetail>(new EventMsg(
591                        hal::wform(L"Set connections totals %1% and uploads %2%.") 
592                                % maxConn % maxUpload)));
593        }
594
595        void set_session_speed(float download, float upload)
596        {
597                int down = (download > 0) ? static_cast<int>(download*1024) : -1;
598                session_.set_download_rate_limit(down);
599                int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
600                session_.set_upload_rate_limit(up);
601               
602                event_log.post(shared_ptr<EventDetail>(new EventMsg(
603                        hal::wform(L"Set session rates at download %1% and upload %2%.") 
604                                % session_.download_rate_limit() % session_.upload_rate_limit())));
605        }
606
607        cache_details get_cache_details() const
608        {
609                libt::cache_status cs = session_.get_cache_status();
610
611                return cache_details(cs.blocks_written, cs.writes, 
612                        cs.blocks_read, cs.blocks_read_hit, cs.reads,
613                        cs.cache_size, cs.read_cache_size);
614        }
615
616        bool ensure_ip_filter_on(progress_callback fn)
617        {
618                try
619                {
620               
621                if (!ip_filter_loaded_)
622                {
623                        ip_filter_load(fn);
624                        ip_filter_loaded_ = true;
625                }
626               
627                if (!ip_filter_on_)
628                {
629                        session_.set_ip_filter(ip_filter_);
630                        ip_filter_on_ = true;
631                        ip_filter_count();
632                }
633               
634                }
635                catch(const std::exception& e)
636                {               
637                        hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
638                                new hal::EventStdException(event_logger::critical, e, L"ensureIpFilterOn"))); 
639
640                        ensure_ip_filter_off();
641                }
642
643                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters on.")));       
644
645                return false;
646        }
647
648        void ensure_ip_filter_off()
649        {
650                session_.set_ip_filter(libt::ip_filter());
651                ip_filter_on_ = false;
652               
653                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters off.")));     
654        }
655
656#       ifndef TORRENT_DISABLE_ENCRYPTION       
657        void ensure_pe_on(const pe_settings& pe_s)
658        {
659                libt::pe_settings pe;
660               
661                switch (pe_s.encrypt_level)
662                {
663                        case 0:
664                                pe.allowed_enc_level = libt::pe_settings::plaintext;
665                                break;
666                        case 1:
667                                pe.allowed_enc_level = libt::pe_settings::rc4;
668                                break;
669                        case 2:
670                                pe.allowed_enc_level = libt::pe_settings::both;
671                                break;
672                        default:
673                                pe.allowed_enc_level = libt::pe_settings::both;
674                               
675                                hal::event_log.post(shared_ptr<hal::EventDetail>(
676                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
677                                                (hal::wform(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % pe_s.encrypt_level).str())));
678                }
679
680                switch (pe_s.conn_in_policy)
681                {
682                        case 0:
683                                pe.in_enc_policy = libt::pe_settings::forced;
684                                break;
685                        case 1:
686                                pe.in_enc_policy = libt::pe_settings::enabled;
687                                break;
688                        case 2:
689                                pe.in_enc_policy = libt::pe_settings::disabled;
690                                break;
691                        default:
692                                pe.in_enc_policy = libt::pe_settings::enabled;
693                               
694                                hal::event_log.post(shared_ptr<hal::EventDetail>(
695                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
696                                                (hal::wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % pe_s.conn_in_policy).str())));
697                }
698
699                switch (pe_s.conn_out_policy)
700                {
701                        case 0:
702                                pe.out_enc_policy = libt::pe_settings::forced;
703                                break;
704                        case 1:
705                                pe.out_enc_policy = libt::pe_settings::enabled;
706                                break;
707                        case 2:
708                                pe.out_enc_policy = libt::pe_settings::disabled;
709                                break;
710                        default:
711                                pe.out_enc_policy = libt::pe_settings::enabled;
712                               
713                                hal::event_log.post(shared_ptr<hal::EventDetail>(
714                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
715                                                (hal::wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % pe_s.conn_out_policy).str())));
716                }
717               
718                pe.prefer_rc4 = pe_s.prefer_rc4;
719               
720                try
721                {
722               
723                session_.set_pe_settings(pe);
724               
725                }
726                catch(const std::exception& e)
727                {
728                        hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
729                                        new hal::EventStdException(event_logger::critical, e, L"ensurePeOn"))); 
730                                       
731                        ensure_pe_off();               
732                }
733               
734                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption on.")));
735        }
736
737        void ensure_pe_off()
738        {
739                libt::pe_settings pe;
740                pe.out_enc_policy = libt::pe_settings::disabled;
741                pe.in_enc_policy = libt::pe_settings::disabled;
742               
743                pe.allowed_enc_level = libt::pe_settings::both;
744                pe.prefer_rc4 = true;
745               
746                session_.set_pe_settings(pe);
747
748                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption off.")));
749        }
750#       endif
751       
752        void set_resolve_countries(bool b)
753        {               
754                resolve_countries_ = b;
755
756                for (torrent_manager::torrent_by_name::iterator i=the_torrents_.begin(), e=the_torrents_.end(); 
757                        i != e; ++i)
758                {
759                        (*i).torrent->set_resolve_countries(resolve_countries_);
760                }
761
762                if (b)                 
763                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Set to resolve countries.")));
764                else                   
765                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Not resolving countries.")));
766        }
767
768        void start_smart_ban_plugin()
769        {
770                session_.add_extension(&libt::create_smart_ban_plugin);
771                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Started smart ban plugin.")));
772        }
773
774        void start_ut_pex_plugin()
775        {
776                session_.add_extension(&libt::create_ut_pex_plugin);
777                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Started uTorrent peer exchange plugin.")));
778        }
779
780        void start_ut_metadata_plugin()
781        {
782                session_.add_extension(&libt::create_ut_metadata_plugin);
783                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Started uTorrent metadata plugin.")));
784        }
785
786        void start_metadata_plugin()
787        {
788                session_.add_extension(&libt::create_metadata_plugin);
789                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Started metadata plugin.")));
790        }
791
792        void ip_v4_filter_block(boost::asio::ip::address_v4 first, boost::asio::ip::address_v4 last)
793        {
794                ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
795                ip_filter_count();
796                ip_filter_changed_ = true;
797        }
798
799        void ip_v6_filter_block(boost::asio::ip::address_v6 first, boost::asio::ip::address_v6 last)
800        {
801                ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
802                ip_filter_count();
803                ip_filter_changed_ = true;
804        }
805
806        size_t ip_filter_size()
807        {
808                return ip_filter_count_;
809        }
810
811        void clear_ip_filter()
812        {
813                ip_filter_ = libt::ip_filter();
814                session_.set_ip_filter(libt::ip_filter());     
815                ip_filter_changed_ = true;
816                ip_filter_count();
817        }
818
819        bool ip_filter_import_dat(boost::filesystem::path file, progress_callback fn, bool octalFix);
820
821        struct 
822        {
823                signaler<> successful_listen;
824                signaler<> torrent_finished;
825
826                boost::signal<bool()> torrent_paused;
827        } 
828        signals;
829
830        void start_alert_handler();
831        void stop_alert_handler();
832        void alert_handler();
833
834        void add_torrent(wpath file, wpath saveDirectory, bool startStopped, bool managed, bit::allocations alloc, 
835                        boost::filesystem::wpath moveToDirectory) 
836        {
837                try 
838                {       
839//              torrent_internal_ptr TIp;
840
841                std::pair<std::string, std::string> names = extract_names(file);
842                wstring xml_name = from_utf8(names.first) + L".xml";
843
844/*              if (false && fs::exists(file.parent_path()/xml_name))
845                {
846                        torrent_standalone tsa;
847                       
848                        if (tsa.load_standalone(file.parent_path()/xml_name))
849                        {
850                                TIp = tsa.torrent;
851                               
852                                TIp->set_save_directory(saveDirectory, true);                   
853                                if (useMoveTo)
854                                        TIp->set_move_to_directory(moveToDirectory);
855
856                                TIp->prepare(file);
857                        }
858                }
859*/
860                torrent_internal_ptr TIp =
861                        the_torrents_.create_torrent(file, saveDirectory, alloc, moveToDirectory);
862
863                if(TIp)
864                {
865                        TIp->set_managed(managed);
866                        TIp->set_transfer_speed(bittorrent().default_torrent_download(), bittorrent().default_torrent_upload());
867                        TIp->set_connection_limit(bittorrent().default_torrent_max_connections(), bittorrent().default_torrent_max_uploads());
868                        TIp->set_resolve_countries(resolve_countries_);
869
870
871                        if (!startStopped) 
872                                TIp->add_to_session();
873                        else
874                                TIp->set_state_stopped();
875                }
876               
877                }
878                catch (const std::exception& e)
879                {
880                        event_log.post(shared_ptr<EventDetail>(
881                                new EventTorrentException(event_logger::critical, event_logger::torrentException, 
882                                        std::string(e.what()), to_utf8(file.string()), std::string("addTorrent"))));
883                }
884        }
885
886        void remove_to_bin(boost::shared_ptr<file_details_vec> files, wpath path)
887        {
888                foreach(file_details file, *files)
889                {
890                        std::wstring file_location = (wform(L"File %1%\\%2%\\%3%") 
891                                % path.file_string() % file.branch % file.filename).str();
892
893                        HAL_DEV_MSG(wform(L"File %1%\\%2%\\%3%") % path.file_string() % file.branch % file.filename);
894                }
895        }
896
897        void removal_thread(torrent_internal_ptr pIT, bool wipeFiles)
898        {
899                try {
900
901                if (!wipeFiles)
902                {
903                        if (pIT->in_session())
904                                session_.remove_torrent(pIT->handle());
905                }
906                else
907                {
908                        if (pIT->in_session())
909                        {
910                                session_.remove_torrent(pIT->handle(), libt::session::delete_files);
911                        }
912                        else
913                        {
914                                //libt::torrent_info m_info = pIT->infoMemory();
915                               
916/*                              // delete the files from disk
917                                std::string error;
918                                std::set<std::string> directories;
919                               
920                                for (libt::torrent_info::file_iterator i = m_info.begin_files(true)
921                                        , end(m_info.end_files(true)); i != end; ++i)
922                                {
923                                        std::string p = (hal::path_to_utf8(pIT->save_directory()) / i->path).string();
924                                        fs::path bp = i->path.parent_path();
925                                       
926                                        std::pair<std::set<std::string>::iterator, bool> ret;
927                                        ret.second = true;
928                                        while (ret.second && !bp.empty())
929                                        {
930                                                std::pair<std::set<std::string>::iterator, bool> ret =
931                                                        directories.insert((hal::path_to_utf8(pIT->save_directory()) / bp).string());
932                                                bp = bp.parent_path();
933                                        }
934                                        if (!fs::remove(hal::from_utf8(p).c_str()) && errno != ENOENT)
935                                                error = std::strerror(errno);
936                                }
937
938                                // remove the directories. Reverse order to delete subdirectories first
939
940                                for (std::set<std::string>::reverse_iterator i = directories.rbegin()
941                                        , end(directories.rend()); i != end; ++i)
942                                {
943                                        if (!fs::remove(hal::from_utf8(*i).c_str()) && errno != ENOENT)
944                                                error = std::strerror(errno);
945                                }
946                                */
947                        }
948                }
949
950                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "removalThread")
951        }
952
953        void remove_torrent(const wstring& filename)
954        {
955                try {
956                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Removing Torrent.")));
957
958                boost::shared_ptr<file_details_vec> files = boost::shared_ptr<file_details_vec>(new file_details_vec());               
959                torrent_internal_ptr pTI = the_torrents_.get(filename);
960
961        //      pTI->get_file_details(*files);         
962        //      thread_t t(bind(&bit_impl::remove_to_bin, this, files, pTI->get_save_directory()));
963
964                libt::torrent_handle handle = pTI->handle();
965                the_torrents_.erase(filename);
966               
967                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Removed, started thread.")));
968               
969                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "remove_torrent")
970        }
971
972        void remove_torrent_wipe_files(const std::wstring& filename, remove_files fn)
973        {
974                try {
975                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Removing Torrent and files.")));
976
977                boost::shared_ptr<file_details_vec> files = boost::shared_ptr<file_details_vec>(new file_details_vec());               
978                torrent_internal_ptr pTI = the_torrents_.get(filename);
979
980                pTI->get_file_details(*files);
981                thread_t t(bind(fn, pTI->get_save_directory(), files));
982
983                pTI->clear_resume_data();
984                pTI->delete_torrent_file();
985
986                the_torrents_.erase(filename);
987               
988                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Removed, started thread.")));
989               
990                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "remove_torrent_wipe_files")
991        }
992
993        void resume_all()
994        {
995                try {
996                       
997                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Resuming torrent.")));
998               
999                for (torrent_manager::torrent_by_name::iterator i=the_torrents_.begin(), e=the_torrents_.end(); i != e;)
1000                {
1001                        wpath file = wpath(hal::app().get_working_directory())/L"torrents"/(*i).torrent->filename();
1002                       
1003                        if (exists(file))
1004                        {               
1005                                try 
1006                                {
1007                                       
1008                                (*i).torrent->prepare(file);   
1009
1010                                switch ((*i).torrent->get_state())
1011                                {
1012                                        case torrent_details::torrent_stopped:
1013                                        case torrent_details::torrent_in_error:
1014                                                break;
1015                                        case torrent_details::torrent_paused:
1016                                                (*i).torrent->add_to_session(true);
1017                                                break;
1018                                        case torrent_details::torrent_active:
1019                                                (*i).torrent->add_to_session(false);
1020                                                (*i).torrent->resume();
1021                                                break;
1022                                        default:
1023                                                assert(false);
1024                                };
1025                               
1026                                ++i;
1027                               
1028                                }
1029                                catch(const libt::duplicate_torrent&)
1030                                {
1031                                        hal::event_log.post(shared_ptr<hal::EventDetail>(
1032                                                new hal::EventDebug(hal::event_logger::debug, L"Encountered duplicate torrent")));
1033                                       
1034                                        ++i; // Harmless, don't worry about it.
1035                                }
1036                                catch(const std::exception& e) 
1037                                {
1038                                        hal::event_log.post(shared_ptr<hal::EventDetail>(
1039                                                new hal::EventStdException(hal::event_logger::warning, e, L"resume_all")));
1040                                       
1041                                        the_torrents_.erase(i++);
1042                                }                       
1043                        }
1044                        else
1045                        {
1046                                the_torrents_.erase(i++);
1047                        }
1048                }
1049               
1050                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "resume_all")
1051        }
1052
1053        bool close_counter(int* count)
1054        {
1055                --(*count);
1056                return true;
1057        }
1058       
1059        void close_all(boost::optional<report_num_active> fn)
1060        {
1061                try 
1062                {       
1063
1064                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Saving torrent data...")));
1065
1066                save_torrent_data();
1067
1068                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Stopping all torrents...")));
1069
1070                session_.pause();               
1071
1072                // Ok this polling loop here is a bit curde, but a blocking wait is actually appropiate.               
1073                { 
1074                int num_active = 1;
1075
1076                while (num_active > 0)
1077                {
1078                        num_active = 0;
1079
1080                        for (torrent_manager::torrent_by_name::iterator i=the_torrents_.begin(), e=the_torrents_.end(); 
1081                                        i != e; ++i)
1082                        {
1083                                if ((*i).torrent && 
1084                                                (((*i).torrent->state() != torrent_details::torrent_stopped
1085                                                        && (*i).torrent->state() != torrent_details::torrent_paused
1086                                                        && (*i).torrent->state() != torrent_details::torrent_in_error)
1087                                                || (*i).torrent->awaiting_resume_data()))
1088                                {
1089#                                       ifdef HAL_TORRENT_DEV_MSGES
1090                                                (*i).torrent->output_torrent_debug_details();
1091#                                       endif
1092                                        num_active += 1;
1093                                }
1094                        }
1095
1096                        event_log.post(shared_ptr<EventDetail>(new EventInfo(hal::wform(L"%1% still active") % (num_active))));
1097
1098                        if (fn) (*fn)(num_active);
1099                        boost::this_thread::sleep(pt::milliseconds(500));
1100                } 
1101               
1102                }
1103               
1104                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"All torrents stopped.")));               
1105               
1106                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "close_all()")
1107        }
1108       
1109        void save_torrent_data()
1110        {       
1111                mutex_t::scoped_lock l(mutex_);
1112                try
1113                {
1114               
1115                the_torrents_.save_to_ini();
1116                bittorrent_ini_.save_data();
1117                       
1118                if (dht_on_) 
1119                {       
1120                        halencode(hal::app().get_working_directory()/L"DHTState.bin", session_.dht_state());
1121                }
1122               
1123                }               
1124                catch(std::exception& e)
1125                {
1126                        event_log.post(shared_ptr<EventDetail>(\
1127                                new EventStdException(event_logger::critical, e, L"save_torrent_data()")));
1128                }
1129        }
1130       
1131        int default_torrent_max_connections() { return default_torrent_max_connections_; }
1132        int default_torrent_max_uploads() { return default_torrent_max_uploads_; }
1133        float default_torrent_download() { return default_torrent_download_; }
1134        float default_torrent_upload() { return default_torrent_upload_; }
1135       
1136private:
1137        bool create_torrent(const create_torrent_params& params, fs::wpath out_file, progress_callback fn);
1138       
1139        libt::session session_; 
1140        mutable mutex_t mutex_;
1141
1142        boost::optional<thread_t> alert_checker_;
1143        bool keepChecking_;
1144       
1145        ini_file bittorrent_ini_;
1146        torrent_manager the_torrents_; 
1147       
1148        int default_torrent_max_connections_;
1149        int default_torrent_max_uploads_;
1150        float default_torrent_download_;
1151        float default_torrent_upload_;
1152       
1153        bool resolve_countries_;
1154        bool ip_filter_on_;
1155        bool ip_filter_loaded_;
1156        bool ip_filter_changed_;
1157        libt::ip_filter ip_filter_;
1158        size_t ip_filter_count_;
1159       
1160        void ip_filter_count();
1161        void ip_filter_load(progress_callback fn);
1162        void ip_filter_import(std::vector<libt::ip_range<boost::asio::ip::address_v4> >& v4,
1163                std::vector<libt::ip_range<boost::asio::ip::address_v6> >& v6);
1164       
1165        bool dht_on_;
1166        libt::dht_settings dht_settings_;
1167        libt::entry dht_state_; 
1168
1169        libt::upnp* upnp_;
1170        libt::natpmp* natpmp_;
1171};
1172
1173}
Note: See TracBrowser for help on using the repository browser.