source: trunk/src/halSession.hpp @ 506

Revision 506, 27.6 KB checked in by Eoin, 12 years ago (diff)

Queue configuration applies correctly.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2008.
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 <libtorrent/file.hpp>
10#include <libtorrent/hasher.hpp>
11#include <libtorrent/storage.hpp>
12#include <libtorrent/file_pool.hpp>
13#include <libtorrent/alert_types.hpp>
14#include <libtorrent/entry.hpp>
15#include <libtorrent/bencode.hpp>
16#include <libtorrent/session.hpp>
17#include <libtorrent/ip_filter.hpp>
18#include <libtorrent/torrent_handle.hpp>
19#include <libtorrent/peer_connection.hpp>
20#include <libtorrent/extensions/metadata_transfer.hpp>
21#include <libtorrent/extensions/ut_pex.hpp>
22
23#include <boost/tuple/tuple.hpp>
24#include <boost/enable_shared_from_this.hpp>
25#include <boost/multi_index_container.hpp>
26#include <boost/multi_index/ordered_index.hpp>
27#include <boost/multi_index/indexed_by.hpp>
28#include <boost/multi_index/identity.hpp>
29#include <boost/multi_index/member.hpp>
30#include <boost/multi_index/tag.hpp>
31#include <boost/serialization/shared_ptr.hpp>
32
33#include "halIni.hpp"
34#include "halTypes.hpp"
35#include "halEvent.hpp"
36#include "halTorrentInternal.hpp"
37#include "halSignaler.hpp"
38
39namespace boost {
40namespace serialization {
41
42template<class Archive, class address_type>
43void save(Archive& ar, const address_type& ip, const unsigned int version)
44{       
45        unsigned long addr = ip.to_ulong();     
46        ar & BOOST_SERIALIZATION_NVP(addr);
47}
48
49template<class Archive, class address_type>
50void load(Archive& ar, address_type& ip, const unsigned int version)
51{       
52        unsigned long addr;
53        ar & BOOST_SERIALIZATION_NVP(addr);     
54        ip = address_type(addr);
55}
56
57template<class Archive, class String, class Traits>
58void save(Archive& ar, const boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
59{       
60        String str = p.string();
61        ar & BOOST_SERIALIZATION_NVP(str);
62}
63
64template<class Archive, class String, class Traits>
65void load(Archive& ar, boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
66{       
67        String str;
68        ar & BOOST_SERIALIZATION_NVP(str);
69
70        p = str;
71}
72
73template<class Archive, class String, class Traits>
74inline void serialize(
75        Archive & ar,
76        boost::filesystem::basic_path<String, Traits>& p,
77        const unsigned int file_version)
78{
79        split_free(ar, p, file_version);           
80}
81
82template<class Archive, class address_type>
83void serialize(Archive& ar, libtorrent::ip_range<address_type>& addr, const unsigned int version)
84{       
85        ar & BOOST_SERIALIZATION_NVP(addr.first);
86        ar & BOOST_SERIALIZATION_NVP(addr.last);
87        addr.flags = libtorrent::ip_filter::blocked;
88}
89
90template<class Archive>
91void serialize(Archive& ar, hal::tracker_detail& tracker, const unsigned int version)
92{       
93        ar & BOOST_SERIALIZATION_NVP(tracker.url);
94        ar & BOOST_SERIALIZATION_NVP(tracker.tier);
95}
96
97} // namespace serialization
98} // namespace boost
99
100BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v4)
101BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v6)
102
103namespace libtorrent
104{
105
106template<class Addr>
107bool operator==(const libtorrent::ip_range<Addr>& lhs, const int flags)
108{
109        return (lhs.flags == flags);
110}
111
112inline
113std::ostream& operator<<(std::ostream& os, libtorrent::ip_range<asio::ip::address_v4>& ip)
114{
115        os << ip.first.to_ulong();
116        os << ip.last.to_ulong();
117       
118        return os;
119}
120
121} // namespace libtorrent
122
123namespace hal
124{
125
126namespace libt = libtorrent;
127
128inline
129bool operator!=(const libt::dht_settings& lhs, const libt::dht_settings& rhs)
130{
131        return lhs.max_peers_reply != rhs.max_peers_reply ||
132                   lhs.search_branching != rhs.search_branching ||
133                   lhs.service_port != rhs.service_port ||
134           lhs.max_fail_count != rhs.max_fail_count;
135}
136
137template<typename Addr>
138void write_range(fs::ofstream& ofs, const libt::ip_range<Addr>& range)
139{ 
140        const typename Addr::bytes_type first = range.first.to_bytes();
141        const typename Addr::bytes_type last = range.last.to_bytes();
142        ofs.write((char*)first.elems, first.size());
143        ofs.write((char*)last.elems, last.size());
144}
145
146template<typename Addr>
147void write_vec_range(fs::ofstream& ofs, const std::vector<libt::ip_range<Addr> >& vec)
148{ 
149        ofs << vec.size();
150       
151        for (typename std::vector<libt::ip_range<Addr> >::const_iterator i=vec.begin(); 
152                i != vec.end(); ++i)
153        {
154                write_range(ofs, *i);
155        }
156}
157
158template<typename Addr>
159void read_range_to_filter(fs::ifstream& ifs, libt::ip_filter& ip_filter)
160{ 
161        typename Addr::bytes_type first;
162        typename Addr::bytes_type last;
163        ifs.read((char*)first.elems, first.size());
164        ifs.read((char*)last.elems, last.size());       
165       
166        ip_filter.add_rule(Addr(first), Addr(last),
167                libt::ip_filter::blocked);
168}
169
170static event_logger::eventLevel lbtAlertToHalEvent(libt::alert::severity_t severity)
171{
172        switch (severity)
173        {
174        case libt::alert::debug:
175                return event_logger::debug;
176       
177        case libt::alert::info:
178                return event_logger::info;
179       
180        case libt::alert::warning:
181                return event_logger::warning;
182       
183        case libt::alert::critical:
184        case libt::alert::fatal:
185                return event_logger::critical;
186       
187        default:
188                return event_logger::none;
189        }
190}
191
192#define HAL_GENERIC_TORRENT_EXCEPTION_CATCH(TORRENT, FUNCTION) \
193catch (const libt::invalid_handle&) \
194{\
195        event_log.post(shared_ptr<EventDetail>( \
196                new EventInvalidTorrent(event_logger::critical, event_logger::invalidTorrent, TORRENT, std::string(FUNCTION)))); \
197}\
198catch (const invalidTorrent& t) \
199{\
200        event_log.post(shared_ptr<EventDetail>( \
201                new EventInvalidTorrent(event_logger::info, event_logger::invalidTorrent, t.who(), std::string(FUNCTION)))); \
202}\
203catch (const std::exception& e) \
204{\
205        event_log.post(shared_ptr<EventDetail>( \
206                new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), TORRENT, std::string(FUNCTION)))); \
207}
208
209class bit_impl
210{
211        friend class bit;
212
213private:
214        bit_impl();     
215public: 
216        ~bit_impl();
217
218        bool listen_on(std::pair<int, int> const& range)
219        {
220                try
221                {
222               
223                if (!session_.is_listening())
224                {
225                        return session_.listen_on(range);
226                }
227                else
228                {
229                        int port = session_.listen_port();
230                       
231                        if (port < range.first || port > range.second)
232                                return session_.listen_on(range);       
233                        else
234                        {
235                                signals.successful_listen();
236                               
237                                return true;
238                        }
239                }
240               
241                }
242                catch (const std::exception& e)
243                {
244                        event_log.post(shared_ptr<EventDetail>(
245                                new EventStdException(event_logger::fatal, e, L"From bit::listenOn.")));
246
247                        return false;
248                }
249                catch(...)
250                {
251                        return false;
252                }
253        }
254
255        int is_listening_on() 
256        {
257                if (!session_.is_listening())
258                        return -1;     
259                else
260                        return session_.listen_port();
261        }
262
263        void stop_listening()
264        {
265                ensure_dht_off();
266                session_.listen_on(std::make_pair(0, 0));
267        }
268
269        bool ensure_dht_on()
270        {
271                if (!dht_on_)
272                {               
273                        try
274                        {
275                        session_.start_dht(dht_state_);
276                        dht_on_ = true;
277                        }
278                        catch(...)
279                        {}
280                }
281                        return dht_on_;
282        }
283
284        void ensure_dht_off()
285        {
286                if (dht_on_)
287                {
288                        session_.stop_dht();           
289                        dht_on_ = false;
290                }
291        }
292
293        void set_dht_settings(int max_peers_reply, int search_branching, 
294                int service_port, int max_fail_count)
295        {
296                libt::dht_settings settings;
297                settings.max_peers_reply = max_peers_reply;
298                settings.search_branching = search_branching;
299                settings.service_port = service_port;
300                settings.max_fail_count = max_fail_count;
301               
302                if (dht_settings_ != settings)
303                {
304                        dht_settings_ = settings;
305                        session_.set_dht_settings(dht_settings_);
306                }
307        }
308
309        void set_mapping(int mapping)
310        {
311                if (mapping != bit::mappingNone)
312                {
313                        if (mapping == bit::mappingUPnP)
314                        {
315                                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting UPnP mapping.")));
316                                session_.stop_upnp();
317                                session_.stop_natpmp();
318
319                                signals.successful_listen.connect_once(bind(&libt::session::start_upnp, &session_));
320                        }
321                        else
322                        {
323                                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting NAT-PMP mapping.")));
324                                session_.stop_upnp();
325                                session_.stop_natpmp();
326
327                                signals.successful_listen.connect_once(bind(&libt::session::start_natpmp, &session_));
328                        }
329                }
330                else
331                {
332                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"No mapping.")));
333                        session_.stop_upnp();
334                        session_.stop_natpmp();
335                }
336        }
337
338        void set_timeouts(int peers, int tracker)
339        {
340                libt::session_settings settings = session_.settings();
341                settings.peer_connect_timeout = peers;
342                settings.tracker_completion_timeout = tracker;
343
344                session_.set_settings(settings);
345
346                event_log.post(shared_ptr<EventDetail>(new EventMsg(
347                        wformat(L"Set Timeouts, peer %1%, tracker %2%.") % peers % tracker)));
348        }
349
350
351        queue_settings get_queue_settings()
352        {               
353                libt::session_settings settings = session_.settings();
354                queue_settings queue;
355
356                queue.auto_manage_interval = settings.auto_manage_interval;
357                queue.active_downloads = settings.active_downloads;
358                queue.active_seeds = settings.active_seeds;
359                queue.seeds_hard_limit = settings.active_limit;
360                queue.seed_ratio_limit = settings.share_ratio_limit;
361                queue.seed_ratio_time_limit = settings.seed_time_ratio_limit;
362                queue.seed_time_limit = settings.seed_time_limit;
363                queue.dont_count_slow_torrents = settings.dont_count_slow_torrents;
364                queue.auto_scrape_min_interval = settings.auto_scrape_min_interval;
365                queue.auto_scrape_interval = settings.auto_scrape_interval;
366                queue.close_redundant_connections = settings.close_redundant_connections;
367
368                return queue;
369        }
370
371        void set_queue_settings(const queue_settings& queue)
372        {
373                libt::session_settings settings = session_.settings();
374
375                settings.auto_manage_interval = queue.auto_manage_interval;
376                settings.active_downloads = queue.active_downloads;
377                settings.active_seeds = queue.active_seeds;
378                settings.active_limit = queue.seeds_hard_limit;
379                settings.share_ratio_limit = queue.seed_ratio_limit;
380                settings.seed_time_ratio_limit = queue.seed_ratio_time_limit;
381                settings.seed_time_limit = queue.seed_time_limit;
382                settings.dont_count_slow_torrents = queue.dont_count_slow_torrents;
383                settings.auto_scrape_min_interval = queue.auto_scrape_min_interval;
384                settings.auto_scrape_interval = queue.auto_scrape_interval;
385                settings.close_redundant_connections = queue.close_redundant_connections;
386
387                session_.set_settings(settings);
388
389                event_log.post(shared_ptr<EventDetail>(new EventMsg(
390                        wformat(L"Set queue parameters, %1% downloads and %2% active seeds.") 
391                                % settings.active_downloads % settings.active_seeds)));
392        }
393
394        void set_session_limits(int maxConn, int maxUpload)
395        {               
396                session_.set_max_uploads(maxUpload);
397                session_.set_max_connections(maxConn);
398               
399                event_log.post(shared_ptr<EventDetail>(new EventMsg(
400                        wformat(L"Set connections totals %1% and uploads %2%.") 
401                                % maxConn % maxUpload)));
402        }
403
404        void set_session_speed(float download, float upload)
405        {
406                int down = (download > 0) ? static_cast<int>(download*1024) : -1;
407                session_.set_download_rate_limit(down);
408                int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
409                session_.set_upload_rate_limit(up);
410               
411                event_log.post(shared_ptr<EventDetail>(new EventMsg(
412                        wformat(L"Set session rates at download %1% and upload %2%.") 
413                                % session_.download_rate_limit() % session_.upload_rate_limit())));
414        }
415
416        bool ensure_ip_filter_on(progress_callback fn)
417        {
418                try
419                {
420               
421                if (!ip_filter_loaded_)
422                {
423                        ip_filter_load(fn);
424                        ip_filter_loaded_ = true;
425                }
426               
427                if (!ip_filter_on_)
428                {
429                        session_.set_ip_filter(ip_filter_);
430                        ip_filter_on_ = true;
431                        ip_filter_count();
432                }
433               
434                }
435                catch(const std::exception& e)
436                {               
437                        hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
438                                new hal::EventStdException(event_logger::critical, e, L"ensureIpFilterOn"))); 
439
440                        ensure_ip_filter_off();
441                }
442
443                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters on.")));       
444
445                return false;
446        }
447
448        void ensure_ip_filter_off()
449        {
450                session_.set_ip_filter(libt::ip_filter());
451                ip_filter_on_ = false;
452               
453                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters off.")));     
454        }
455
456        #ifndef TORRENT_DISABLE_ENCRYPTION     
457        void ensure_pe_on(int enc_level, int in_enc_policy, int out_enc_policy, bool prefer_rc4)
458        {
459                libt::pe_settings pe;
460               
461                switch (enc_level)
462                {
463                        case 0:
464                                pe.allowed_enc_level = libt::pe_settings::plaintext;
465                                break;
466                        case 1:
467                                pe.allowed_enc_level = libt::pe_settings::rc4;
468                                break;
469                        case 2:
470                                pe.allowed_enc_level = libt::pe_settings::both;
471                                break;
472                        default:
473                                pe.allowed_enc_level = libt::pe_settings::both;
474                               
475                                hal::event_log.post(shared_ptr<hal::EventDetail>(
476                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
477                                                (wformat(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % enc_level).str())));
478                }
479
480                switch (in_enc_policy)
481                {
482                        case 0:
483                                pe.in_enc_policy = libt::pe_settings::forced;
484                                break;
485                        case 1:
486                                pe.in_enc_policy = libt::pe_settings::enabled;
487                                break;
488                        case 2:
489                                pe.in_enc_policy = libt::pe_settings::disabled;
490                                break;
491                        default:
492                                pe.in_enc_policy = libt::pe_settings::enabled;
493                               
494                                hal::event_log.post(shared_ptr<hal::EventDetail>(
495                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
496                                                (wformat(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
497                }
498
499                switch (out_enc_policy)
500                {
501                        case 0:
502                                pe.out_enc_policy = libt::pe_settings::forced;
503                                break;
504                        case 1:
505                                pe.out_enc_policy = libt::pe_settings::enabled;
506                                break;
507                        case 2:
508                                pe.out_enc_policy = libt::pe_settings::disabled;
509                                break;
510                        default:
511                                pe.out_enc_policy = libt::pe_settings::enabled;
512                               
513                                hal::event_log.post(shared_ptr<hal::EventDetail>(
514                                        new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
515                                                (wformat(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
516                }
517               
518                pe.prefer_rc4 = prefer_rc4;
519               
520                try
521                {
522               
523                session_.set_pe_settings(pe);
524               
525                }
526                catch(const std::exception& e)
527                {
528                        hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
529                                        new hal::EventStdException(event_logger::critical, e, L"ensurePeOn"))); 
530                                       
531                        ensure_pe_off();               
532                }
533               
534                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption on.")));
535        }
536
537        void ensure_pe_off()
538        {
539                libt::pe_settings pe;
540                pe.out_enc_policy = libt::pe_settings::disabled;
541                pe.in_enc_policy = libt::pe_settings::disabled;
542               
543                pe.allowed_enc_level = libt::pe_settings::both;
544                pe.prefer_rc4 = true;
545               
546                session_.set_pe_settings(pe);
547
548                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption off.")));
549        }
550        #endif
551
552        void ip_v4_filter_block(asio::ip::address_v4 first, asio::ip::address_v4 last)
553        {
554                ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
555                ip_filter_count();
556                ip_filter_changed_ = true;
557        }
558
559        void ip_v6_filter_block(asio::ip::address_v6 first, asio::ip::address_v6 last)
560        {
561                ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
562                ip_filter_count();
563                ip_filter_changed_ = true;
564        }
565
566        size_t ip_filter_size()
567        {
568                return ip_filter_count_;
569        }
570
571        void clear_ip_filter()
572        {
573                ip_filter_ = libt::ip_filter();
574                session_.set_ip_filter(libt::ip_filter());     
575                ip_filter_changed_ = true;
576                ip_filter_count();
577        }
578
579        bool ip_filter_import_dat(boost::filesystem::path file, progress_callback fn, bool octalFix);
580
581        struct 
582        {
583                signaler<> successful_listen;
584                signaler<> torrent_finished;
585        } 
586        signals;
587
588        void start_alert_handler();
589        void stop_alert_handler();
590        void alert_handler();
591
592        void add_torrent(wpath file, wpath saveDirectory, bool startStopped, bool compactStorage, 
593                        boost::filesystem::wpath moveToDirectory, bool useMoveTo) 
594        {
595                try 
596                {       
597                torrent_internal_ptr TIp;
598
599                std::pair<std::string, std::string> names = extract_names(file);
600                wstring xml_name = from_utf8(names.first) + L".xml";
601
602                if (fs::exists(file.branch_path()/xml_name))
603                {
604                        torrent_standalone tsa;
605                       
606                        if (tsa.load_standalone(file.branch_path()/xml_name))
607                        {
608                                TIp = tsa.torrent;
609                               
610                                TIp->set_save_directory(saveDirectory, true);                   
611                                if (useMoveTo)
612                                        TIp->set_move_to_directory(moveToDirectory);
613
614                                TIp->prepare(file);
615                        }
616                }
617
618                if (!TIp)
619                {
620                        if (useMoveTo)
621                                TIp.reset(new torrent_internal(file, saveDirectory, compactStorage, moveToDirectory));         
622                        else
623                                TIp.reset(new torrent_internal(file, saveDirectory, compactStorage));
624
625                        TIp->setTransferSpeed(bittorrent().defTorrentDownload(), bittorrent().defTorrentUpload());
626                        TIp->setConnectionLimit(bittorrent().defTorrentMaxConn(), bittorrent().defTorrentMaxUpload());
627                }
628               
629                std::pair<TorrentManager::torrentByName::iterator, bool> p =
630                        the_torrents_.insert(TIp);
631               
632                if (p.second)
633                {
634                        torrent_internal_ptr me = the_torrents_.get(TIp->name());               
635                       
636                        if (!startStopped) 
637                                me->add_to_session();
638                        else
639                                me->set_state_stopped();
640                }
641               
642                }
643                catch (const std::exception& e)
644                {
645                        event_log.post(shared_ptr<EventDetail>(
646                                new EventTorrentException(event_logger::critical, event_logger::torrentException, 
647                                        std::string(e.what()), to_utf8(file.string()), std::string("addTorrent"))));
648                }
649        }
650
651        std::pair<libt::entry, libt::entry> prep_torrent(wpath filename, wpath saveDirectory)
652        {
653                libt::entry metadata = haldecode(filename);
654                libt::torrent_info info(metadata);
655               
656                wstring torrentName = hal::from_utf8_safe(info.name());
657                if (!boost::find_last(torrentName, L".torrent")) 
658                        torrentName += L".torrent";
659               
660                wpath torrentFilename = torrentName;
661                const wpath resumeFile = workingDirectory/L"resume"/torrentFilename.leaf();
662               
663                //  vvv Handle old naming style!
664                const wpath oldResumeFile = workingDirectory/L"resume"/filename.leaf();
665               
666                if (filename.leaf() != torrentFilename.leaf() && exists(oldResumeFile))
667                        fs::rename(oldResumeFile, resumeFile);
668                //  ^^^ Handle old naming style!       
669               
670                libt::entry resumeData; 
671               
672                if (fs::exists(resumeFile)) 
673                {
674                        try 
675                        {
676                                resumeData = haldecode(resumeFile);
677                        }
678                        catch(std::exception &e) 
679                        {               
680                                hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
681                                        new hal::EventStdException(event_logger::critical, e, L"prepTorrent, Resume"))); 
682               
683                                fs::remove(resumeFile);
684                        }
685                }
686
687                if (!fs::exists(workingDirectory/L"torrents"))
688                        fs::create_directory(workingDirectory/L"torrents");
689
690                if (!fs::exists(workingDirectory/L"torrents"/torrentFilename.leaf()))
691                        fs::copy_file(filename.string(), workingDirectory/L"torrents"/torrentFilename.leaf());
692
693                if (!fs::exists(saveDirectory))
694                        fs::create_directory(saveDirectory);
695               
696                return std::make_pair(metadata, resumeData);
697        }
698
699        void removal_thread(torrent_internal_ptr pIT, bool wipeFiles)
700        {
701                try {
702
703                if (!wipeFiles)
704                {
705                        session_.remove_torrent(pIT->handle());
706                }
707                else
708                {
709                        if (pIT->in_session())
710                        {
711                                session_.remove_torrent(pIT->handle(), libt::session::delete_files);
712                        }
713                        else
714                        {
715                                libt::torrent_info m_info = pIT->infoMemory();
716                               
717/*                              // delete the files from disk
718                                std::string error;
719                                std::set<std::string> directories;
720                               
721                                for (libt::torrent_info::file_iterator i = m_info.begin_files(true)
722                                        , end(m_info.end_files(true)); i != end; ++i)
723                                {
724                                        std::string p = (hal::path_to_utf8(pIT->saveDirectory()) / i->path).string();
725                                        fs::path bp = i->path.branch_path();
726                                       
727                                        std::pair<std::set<std::string>::iterator, bool> ret;
728                                        ret.second = true;
729                                        while (ret.second && !bp.empty())
730                                        {
731                                                std::pair<std::set<std::string>::iterator, bool> ret =
732                                                        directories.insert((hal::path_to_utf8(pIT->saveDirectory()) / bp).string());
733                                                bp = bp.branch_path();
734                                        }
735                                        if (!fs::remove(hal::from_utf8(p).c_str()) && errno != ENOENT)
736                                                error = std::strerror(errno);
737                                }
738
739                                // remove the directories. Reverse order to delete subdirectories first
740
741                                for (std::set<std::string>::reverse_iterator i = directories.rbegin()
742                                        , end(directories.rend()); i != end; ++i)
743                                {
744                                        if (!fs::remove(hal::from_utf8(*i).c_str()) && errno != ENOENT)
745                                                error = std::strerror(errno);
746                                }
747                                */
748                        }
749                }
750
751                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "removalThread")
752        }
753
754        void remove_torrent(const wstring& filename)
755        {
756                try {
757               
758                torrent_internal_ptr pTI = the_torrents_.get(filename);
759                libt::torrent_handle handle = pTI->handle();
760                the_torrents_.erase(filename);
761               
762                thread_t t(bind(&bit_impl::removal_thread, this, pTI, false)); 
763               
764                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "remove_torrent")
765        }
766
767        void remove_torrent_wipe_files(const std::wstring& filename)
768        {
769                try {
770               
771                torrent_internal_ptr pTI = the_torrents_.get(filename);
772                libt::torrent_handle handle = pTI->handle();
773                the_torrents_.erase(filename);
774               
775                thread_t t(bind(&bit_impl::removal_thread, this, pTI, true));   
776               
777                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "remove_torrent_wipe_files")
778        }
779
780        void resume_all()
781        {
782                try {
783                       
784                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Resuming torrent.")));
785               
786                for (TorrentManager::torrentByName::iterator i=the_torrents_.begin(), e=the_torrents_.end(); i != e;)
787                {
788                        wpath file = wpath(workingDirectory)/L"torrents"/(*i).torrent->filename();
789                       
790                        if (exists(file))
791                        {               
792                                try 
793                                {
794                                       
795                                (*i).torrent->prepare(file);   
796
797                                switch ((*i).torrent->state())
798                                {
799                                        case TorrentDetail::torrent_stopped:
800                                                break;
801                                        case TorrentDetail::torrent_paused:
802                                                (*i).torrent->add_to_session(true);
803                                                break;
804                                        case TorrentDetail::torrent_active:
805                                                (*i).torrent->add_to_session(false);
806                                                break;
807                                        default:
808                                                assert(false);
809                                };
810                               
811                                ++i;
812                               
813                                }
814                                catch(const libt::duplicate_torrent&)
815                                {
816                                        hal::event_log.post(shared_ptr<hal::EventDetail>(
817                                                new hal::EventDebug(hal::event_logger::debug, L"Encountered duplicate torrent")));
818                                       
819                                        ++i; // Harmless, don't worry about it.
820                                }
821                                catch(const std::exception& e) 
822                                {
823                                        hal::event_log.post(shared_ptr<hal::EventDetail>(
824                                                new hal::EventStdException(hal::event_logger::warning, e, L"resumeAll")));
825                                       
826                                        the_torrents_.erase(i++);
827                                }                       
828                        }
829                        else
830                        {
831                                the_torrents_.erase(i++);
832                        }
833                }
834               
835                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll")
836        }
837
838        void close_all(boost::optional<report_num_active> fn)
839        {
840                try 
841                {       
842                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Saving torrent data...")));
843
844                save_torrent_data();
845
846                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Stopping all torrents...")));
847               
848                for (TorrentManager::torrentByName::iterator i=the_torrents_.begin(), e=the_torrents_.end(); 
849                        i != e; ++i)
850                {
851                        (*i).torrent->stop();
852                }
853               
854                // Ok this polling loop here is a bit curde, but a blocking wait is actually appropiate.
855                for (int num_active = -1; num_active != 0; )
856                {
857                        num_active = 0;
858
859                        for (TorrentManager::torrentByName::iterator i=the_torrents_.begin(), e=the_torrents_.end(); 
860                                        i != e; ++i)
861                        {
862                                if ((*i).torrent->state() != TorrentDetail::torrent_stopped)
863                                        ++num_active;
864                        }
865                       
866                        event_log.post(shared_ptr<EventDetail>(new EventInfo(wformat(L"%1% still active") % num_active)));
867
868                        if (fn) (*fn)(num_active);
869                        Sleep(200);
870                }
871               
872                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"All torrents stopped.")));               
873                event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Fast-resume data written.")));
874               
875                } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll")
876        }
877       
878        void save_torrent_data()
879        {       
880                mutex_t::scoped_lock l(mutex_);
881                try
882                {
883               
884                the_torrents_.save_to_ini();
885                bittorrentIni.save_data();
886                       
887                if (dht_on_) 
888                {       
889                        halencode(workingDirectory/L"DHTState.bin", session_.dht_state());
890                }
891               
892                }               
893                catch(std::exception& e)
894                {
895                        event_log.post(shared_ptr<EventDetail>(\
896                                new EventStdException(event_logger::critical, e, L"saveTorrentData")));
897                }
898        }
899       
900        int defTorrentMaxConn() { return defTorrentMaxConn_; }
901        int defTorrentMaxUpload() { return defTorrentMaxUpload_; }
902        float defTorrentDownload() { return defTorrentDownload_; }
903        float defTorrentUpload() { return defTorrentUpload_; }
904       
905        const wpath workingDir() { return workingDirectory; };
906
907private:
908
909        bool create_torrent(const create_torrent_params& params, fs::wpath out_file, progress_callback fn)
910        {               
911/*     
912        try
913        {
914                libt::file_storage fs;
915                libt::file_pool f_pool;
916
917
918                HAL_DEV_MSG(L"Files");
919                for (file_size_pairs_t::const_iterator i = params.file_size_pairs.begin(), e = params.file_size_pairs.end();
920                                i != e; ++i)
921                {
922                        HAL_DEV_MSG(wformat(L"file path: %1%, size: %2%") % (*i).first % (*i).second);
923                        f_pool->add_file(to_utf8((*i).first.string()), (*i).second);
924                }
925
926                int piece_size = params.piece_size;
927                HAL_DEV_MSG(wformat(L"piece size: %1%") % piece_size);
928               
929                libt::create_torrent t(fs, piece_size);
930               
931                boost::scoped_ptr<libt::storage_interface> store(
932                        libt::default_storage_constructor(t_info, to_utf8(params.root_path.string()),
933                                f_pool));
934
935                HAL_DEV_MSG(L"Trackers");
936                for (tracker_details_t::const_iterator i = params.trackers.begin(), e = params.trackers.end();
937                                i != e; ++i)
938                {
939                        HAL_DEV_MSG(wformat(L"URL: %1%, Tier: %2%") % (*i).url % (*i).tier);
940                        t_info->add_tracker(to_utf8((*i).url), (*i).tier);
941                }
942
943                HAL_DEV_MSG(L"Web Seeds");
944                for (web_seed_details_t::const_iterator i = params.web_seeds.begin(), e = params.web_seeds.end();
945                                i != e; ++i)
946                {
947                        HAL_DEV_MSG(wformat(L"URL: %1%") % (*i).url);
948                        t_info->add_url_seed(to_utf8((*i).url));
949                }
950
951                HAL_DEV_MSG(L"DHT Nodes");
952                for (dht_node_details_t::const_iterator i = params.dht_nodes.begin(), e = params.dht_nodes.end();
953                                i != e; ++i)
954                {
955                        HAL_DEV_MSG(wformat(L"URL: %1%, port: %2%") % (*i).url % (*i).port);
956                        t_info->add_node(hal::make_pair(to_utf8((*i).url), (*i).port));
957                }
958
959                // calculate the hash for all pieces
960                int num = t_info->num_pieces();
961                std::vector<char> piece_buf(piece_size);
962
963                for (int i = 0; i < num; ++i)
964                {
965                        store->read(&piece_buf[0], i, 0, t_info->piece_size(i));
966
967                        libt::hasher h(&piece_buf[0], t_info->piece_size(i));
968                        t_info->set_hash(i, h.final());
969
970                        if (fn(100*i / num, hal::app().res_wstr(HAL_NEWT_HASHING_PIECES)))
971                        {
972                                // User canceled torrent creation.
973
974                                hal::event_log.post(shared_ptr<hal::EventDetail>(
975                                        new hal::EventMsg(hal::app().res_wstr(HAL_NEWT_CREATION_CANCELED), hal::event_logger::info)));
976
977                                return true;
978                        }
979                }
980
981                t_info->set_creator(to_utf8(params.creator).c_str());
982                t_info->set_comment(to_utf8(params.comment).c_str());
983               
984                t_info->set_priv(params.private_torrent);
985
986                // create the torrent and print it to out
987                libt::entry e = t_info->create_torrent();
988                halencode(out_file, e);
989                }
990                catch(const std::exception& e)
991                {
992                        event_log.post(shared_ptr<EventDetail>(
993                                new EventStdException(event_logger::fatal, e, L"create_torrent")));
994                }       
995*/
996                return false;
997        }
998       
999        libt::session session_; 
1000        mutable mutex_t mutex_;
1001
1002        boost::optional<thread_t> alert_checker_;
1003        bool keepChecking_;
1004       
1005        static wpath workingDirectory;
1006        ini_file bittorrentIni;
1007        TorrentManager the_torrents_;   
1008       
1009        int defTorrentMaxConn_;
1010        int defTorrentMaxUpload_;
1011        float defTorrentDownload_;
1012        float defTorrentUpload_;
1013       
1014        bool ip_filter_on_;
1015        bool ip_filter_loaded_;
1016        bool ip_filter_changed_;
1017        libt::ip_filter ip_filter_;
1018        size_t ip_filter_count_;
1019       
1020        void ip_filter_count();
1021        void ip_filter_load(progress_callback fn);
1022        void ip_filter_import(std::vector<libt::ip_range<asio::ip::address_v4> >& v4,
1023                std::vector<libt::ip_range<asio::ip::address_v6> >& v6);
1024       
1025        bool dht_on_;
1026        libt::dht_settings dht_settings_;
1027        libt::entry dht_state_;
1028       
1029};
1030
1031}
Note: See TracBrowser for help on using the repository browser.