source: branch_0_3_1/src/halTorrent.cpp @ 565

Revision 565, 56.4 KB checked in by Eoin, 11 years ago (diff)

Win32 exception catchers backported to branch.

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#include "stdAfx.hpp"
8
9#define TORRENT_MAX_ALERT_TYPES 20
10
11#include <libtorrent/file.hpp>
12#include <libtorrent/hasher.hpp>
13#include <libtorrent/storage.hpp>
14#include <libtorrent/file_pool.hpp>
15#include <libtorrent/alert_types.hpp>
16#include <libtorrent/entry.hpp>
17#include <libtorrent/bencode.hpp>
18#include <libtorrent/session.hpp>
19#include <libtorrent/ip_filter.hpp>
20#include <libtorrent/torrent_handle.hpp>
21#include <libtorrent/peer_connection.hpp>
22#include <libtorrent/extensions/metadata_transfer.hpp>
23#include <libtorrent/extensions/ut_pex.hpp>
24
25#include "global/wtl_app.hpp"
26#include "global/string_conv.hpp"
27#include "global/ini_adapter.hpp"
28
29#include "halTorrent.hpp"
30#include "halTypes.hpp"
31#include "halEvent.hpp"
32#include "halSignaler.hpp"
33
34#define foreach BOOST_FOREACH
35
36namespace boost {
37namespace serialization {
38
39#define IP_SAVE  3
40
41template<class Archive, class address_type>
42void save(Archive& ar, const address_type& ip, const unsigned int version)
43{       
44#if IP_SAVE == 1
45        typename address_type::bytes_type bytes = ip.to_bytes();       
46        for (typename address_type::bytes_type::iterator i=bytes.begin(); i != bytes.end(); ++i)
47                ar & BOOST_SERIALIZATION_NVP(*i);
48#elif IP_SAVE == 2
49        string dotted = ip.to_string(); 
50        ar & BOOST_SERIALIZATION_NVP(dotted);
51#elif IP_SAVE == 3
52        unsigned long addr = ip.to_ulong();     
53        ar & BOOST_SERIALIZATION_NVP(addr);
54#endif
55}
56
57template<class Archive, class address_type>
58void load(Archive& ar, address_type& ip, const unsigned int version)
59{       
60#if IP_SAVE == 1
61        typename address_type::bytes_type bytes;       
62        for (typename address_type::bytes_type::iterator i=bytes.begin(); i != bytes.end(); ++i)
63                ar & BOOST_SERIALIZATION_NVP(*i);       
64        ip = address_type(bytes);
65#elif IP_SAVE == 2     
66        string dotted;
67        ar & BOOST_SERIALIZATION_NVP(dotted);   
68        ip = address_type::from_string(dotted);
69#elif IP_SAVE == 3
70        unsigned long addr;
71        ar & BOOST_SERIALIZATION_NVP(addr);     
72        ip = address_type(addr);
73#endif
74}
75
76template<class Archive, class String, class Traits>
77void save(Archive& ar, const boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
78{       
79        String str = p.string();
80        ar & BOOST_SERIALIZATION_NVP(str);
81}
82
83template<class Archive, class String, class Traits>
84void load(Archive& ar, boost::filesystem::basic_path<String, Traits>& p, const unsigned int version)
85{       
86        String str;
87        ar & BOOST_SERIALIZATION_NVP(str);
88
89        p = str;
90}
91
92template<class Archive, class String, class Traits>
93inline void serialize(
94        Archive & ar,
95        boost::filesystem::basic_path<String, Traits>& p,
96        const unsigned int file_version
97){
98        split_free(ar, p, file_version);           
99}
100
101template<class Archive, class address_type>
102void serialize(Archive& ar, libtorrent::ip_range<address_type>& addr, const unsigned int version)
103{       
104        ar & BOOST_SERIALIZATION_NVP(addr.first);
105        ar & BOOST_SERIALIZATION_NVP(addr.last);
106        addr.flags = libtorrent::ip_filter::blocked;
107}
108
109template<class Archive>
110void serialize(Archive& ar, hal::tracker_detail& tracker, const unsigned int version)
111{       
112        ar & BOOST_SERIALIZATION_NVP(tracker.url);
113        ar & BOOST_SERIALIZATION_NVP(tracker.tier);
114}
115
116} // namespace serialization
117} // namespace boost
118
119BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v4)
120BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v6)
121
122namespace libtorrent
123{
124template<class Addr>
125bool operator==(const libtorrent::ip_range<Addr>& lhs, const int flags)
126{
127        return (lhs.flags == flags);
128}
129
130std::ostream& operator<<(std::ostream& os, libtorrent::ip_range<asio::ip::address_v4>& ip)
131{
132        os << ip.first.to_ulong();
133        os << ip.last.to_ulong();
134       
135        return os;
136}
137
138} // namespace libtorrent
139
140#include "halTorrentInternal.hpp"
141
142namespace hal
143{
144        libtorrent::session* torrent_internal::the_session_ = 0;
145        wpath torrent_internal::workingDir_;
146}
147
148namespace hal
149{
150
151bit& bittorrent()
152{
153        static bit t;
154        return t;
155}
156
157bool operator!=(const libt::dht_settings& lhs, const libt::dht_settings& rhs)
158{
159        return lhs.max_peers_reply != rhs.max_peers_reply ||
160                   lhs.search_branching != rhs.search_branching ||
161                   lhs.service_port != rhs.service_port ||
162           lhs.max_fail_count != rhs.max_fail_count;
163}
164
165template<typename Addr>
166void write_range(fs::ofstream& ofs, const libt::ip_range<Addr>& range)
167{ 
168        const typename Addr::bytes_type first = range.first.to_bytes();
169        const typename Addr::bytes_type last = range.last.to_bytes();
170        ofs.write((char*)first.elems, first.size());
171        ofs.write((char*)last.elems, last.size());
172}
173
174template<typename Addr>
175void write_vec_range(fs::ofstream& ofs, const std::vector<libt::ip_range<Addr> >& vec)
176{ 
177        ofs << vec.size();
178       
179        for (typename std::vector<libt::ip_range<Addr> >::const_iterator i=vec.begin(); 
180                i != vec.end(); ++i)
181        {
182                write_range(ofs, *i);
183        }
184}
185
186template<typename Addr>
187void read_range_to_filter(fs::ifstream& ifs, libt::ip_filter& ip_filter)
188{ 
189        typename Addr::bytes_type first;
190        typename Addr::bytes_type last;
191        ifs.read((char*)first.elems, first.size());
192        ifs.read((char*)last.elems, last.size());       
193       
194        ip_filter.add_rule(Addr(first), Addr(last),
195                libt::ip_filter::blocked);
196}
197
198static event_logger::eventLevel lbtAlertToHalEvent(libt::alert::severity_t severity)
199{
200        switch (severity)
201        {
202        case libt::alert::debug:
203                return event_logger::debug;
204       
205        case libt::alert::info:
206                return event_logger::info;
207       
208        case libt::alert::warning:
209                return event_logger::warning;
210       
211        case libt::alert::critical:
212        case libt::alert::fatal:
213                return event_logger::critical;
214       
215        default:
216                return event_logger::none;
217        }
218}
219
220const PeerDetails& TorrentDetail::peerDetails() const
221{
222        if (!peerDetailsFilled_)
223        {
224                bittorrent().getAllPeerDetails(hal::to_utf8(name_), peerDetails_);
225                peerDetailsFilled_ = true;
226        }
227       
228        return peerDetails_;
229}
230
231const FileDetails& TorrentDetail::fileDetails() const
232{
233        if (!fileDetailsFilled_)
234        {
235                bittorrent().getAllFileDetails(hal::to_utf8(name_), fileDetails_);
236                fileDetailsFilled_ = true;
237        }
238       
239        return fileDetails_;
240}
241
242bool nameLess(const TorrentDetail_ptr& left, const TorrentDetail_ptr& right)
243{
244        return left->state() < right->state();
245}
246
247void TorrentDetails::sort(
248        boost::function<bool (const TorrentDetail_ptr&, const TorrentDetail_ptr&)> fn) const
249{
250        std::stable_sort(torrents_.begin(), torrents_.end(), fn);
251}
252
253web_seed_or_dht_node_detail::web_seed_or_dht_node_detail() : 
254        url(L""), 
255        port(-1), 
256        type(hal::app().res_wstr(HAL_INT_NEWT_ADD_PEERS_WEB)) 
257{}
258
259web_seed_or_dht_node_detail::web_seed_or_dht_node_detail(std::wstring u) : 
260        url(u), 
261        port(-1), 
262        type(hal::app().res_wstr(HAL_INT_NEWT_ADD_PEERS_WEB)) 
263{}
264
265web_seed_or_dht_node_detail::web_seed_or_dht_node_detail(std::wstring u, int p) : 
266        url(u), 
267        port(p), 
268        type(hal::app().res_wstr(HAL_INT_NEWT_ADD_PEERS_DHT)) 
269{}
270
271class bit_impl
272{
273        friend class bit;
274       
275public:
276       
277        ~bit_impl()
278        {
279                stopAlertHandler();
280               
281                //saveTorrentData();
282               
283                try
284                {
285               
286                if (ip_filter_changed_)
287                {       
288                        fs::ofstream ofs(workingDirectory/L"IPFilter.bin", std::ios::binary);
289//                      boost::archive::binary_oarchive oba(ofs);
290                       
291                        libt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();   
292                       
293                        std::vector<libt::ip_range<asio::ip::address_v4> > v4(vectors.get<0>());
294                        std::vector<libt::ip_range<asio::ip::address_v6> > v6(vectors.get<1>());
295                       
296                        v4.erase(std::remove(v4.begin(), v4.end(), 0), v4.end());
297                        v6.erase(std::remove(v6.begin(), v6.end(), 0), v6.end());
298
299                        write_vec_range(ofs, v4);
300//                      write_vec_range(ofs, v6);
301                }       
302                }
303                HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit_impl::~bit_impl()")
304        }
305
306        struct 
307        {
308                signaler<> successful_listen;
309                signaler<> torrent_finished;
310        } 
311        signals;
312
313        void stopAlertHandler()
314        {
315                mutex_t::scoped_lock l(mutex_);
316
317                keepChecking_ = false;
318        }
319               
320        void alertHandler()
321        {
322                try
323                {
324                        mutex_t::scoped_lock l(mutex_);
325
326                        if (keepChecking_)
327                        {
328                       
329                        std::auto_ptr<libt::alert> p_alert = theSession.pop_alert();
330                       
331                        class AlertHandler
332                        {
333                        public:
334                        AlertHandler(bit_impl& bit_impl) :
335                                bit_impl_(bit_impl)
336                        {}
337                       
338                        void operator()(libt::torrent_finished_alert const& a) const
339                        {
340                                event_log.post(shared_ptr<EventDetail>(
341                                        new EventMsg((wform(hal::app().res_wstr(LBT_EVENT_TORRENT_FINISHED)) 
342                                                        % get(a.handle)->name()), 
343                                                event_logger::info, a.timestamp())));
344                               
345                                get(a.handle)->finished();     
346                        }
347                       
348                        void operator()(libt::torrent_paused_alert const& a) const
349                        {
350                                event_log.post(shared_ptr<EventDetail>(
351                                        new EventMsg((wform(hal::app().res_wstr(LBT_EVENT_TORRENT_PAUSED)) 
352                                                        % get(a.handle)->name()), 
353                                                event_logger::info, a.timestamp())));
354
355                                get(a.handle)->signals().torrent_paused();
356                        }
357                       
358                        void operator()(libt::peer_error_alert const& a) const
359                        {
360                                event_log.post(shared_ptr<EventDetail>(
361                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
362                                                wform(hal::app().res_wstr(HAL_PEER_ALERT))
363                                                        % hal::from_utf8_safe(a.msg())
364                                                        % hal::from_utf8_safe(a.ip.address().to_string()))
365                                )       );                             
366                        }
367                               
368                        void operator()(libt::peer_ban_alert const& a) const
369                        {
370                                event_log.post(shared_ptr<EventDetail>(
371                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
372                                                wform(hal::app().res_wstr(HAL_PEER_BAN_ALERT))
373                                                        % get(a.handle)->name()
374                                                        % hal::from_utf8_safe(a.ip.address().to_string()))
375                                )       );                             
376                        }
377                               
378                        void operator()(libt::hash_failed_alert const& a) const
379                        {
380                                event_log.post(shared_ptr<EventDetail>(
381                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
382                                                wform(hal::app().res_wstr(HAL_HASH_FAIL_ALERT))
383                                                        % get(a.handle)->name()
384                                                        % a.piece_index)
385                                )       );                             
386                        }
387                               
388                        void operator()(libt::url_seed_alert const& a) const
389                        {
390                                event_log.post(shared_ptr<EventDetail>(
391                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
392                                                wform(hal::app().res_wstr(HAL_URL_SEED_ALERT))
393                                                        % get(a.handle)->name()
394                                                        % hal::from_utf8_safe(a.url)
395                                                        % hal::from_utf8_safe(a.msg()))
396                                )       );                             
397                        }
398                       
399                        void operator()(libt::tracker_warning_alert const& a) const
400                        {
401                                event_log.post(shared_ptr<EventDetail>(
402                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
403                                                wform(hal::app().res_wstr(HAL_TRACKER_WARNING_ALERT))
404                                                        % get(a.handle)->name()
405                                                        % hal::from_utf8_safe(a.msg()))
406                                )       );                             
407                        }
408                       
409                        void operator()(libt::tracker_announce_alert const& a) const
410                        {
411                                event_log.post(shared_ptr<EventDetail>(
412                                        new EventMsg((wform(hal::app().res_wstr(HAL_TRACKER_ANNOUNCE_ALERT)) 
413                                                        % get(a.handle)->name()), 
414                                                event_logger::info, a.timestamp())));
415                        }
416                       
417                        void operator()(libt::tracker_alert const& a) const
418                        {
419                                event_log.post(shared_ptr<EventDetail>(
420                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
421                                                wform(hal::app().res_wstr(HAL_TRACKER_ALERT))
422                                                        % get(a.handle)->name()
423                                                        % hal::from_utf8_safe(a.msg())
424                                                        % a.times_in_row
425                                                        % a.status_code)
426                                )       );                             
427                        }
428                       
429                        void operator()(libt::tracker_reply_alert const& a) const
430                        {
431                                event_log.post(shared_ptr<EventDetail>(
432                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
433                                                wform(hal::app().res_wstr(HAL_TRACKER_REPLY_ALERT))
434                                                        % get(a.handle)->name()
435                                                        % hal::from_utf8_safe(a.msg())
436                                                        % a.num_peers)
437                                )       );                             
438                        }
439                       
440                        void operator()(libt::fastresume_rejected_alert const& a) const
441                        {
442                                event_log.post(shared_ptr<EventDetail>(
443                                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
444                                                wform(hal::app().res_wstr(HAL_FAST_RESUME_ALERT))
445                                                        % get(a.handle)->name()
446                                                        % hal::from_utf8_safe(a.msg()))
447                                )       );                             
448                        }
449                       
450                        void operator()(libt::piece_finished_alert const& a) const
451                        {
452                                event_log.post(shared_ptr<EventDetail>(
453                                        new EventGeneral(event_logger::debug, a.timestamp(),
454                                                wform(hal::app().res_wstr(HAL_PIECE_FINISHED_ALERT))
455                                                        % get(a.handle)->name()
456                                                        % a.piece_index)
457                                )       );                             
458                        }
459                       
460                        void operator()(libt::block_finished_alert const& a) const
461                        {
462                                event_log.post(shared_ptr<EventDetail>(
463                                        new EventGeneral(event_logger::debug, a.timestamp(),
464                                                wform(hal::app().res_wstr(HAL_BLOCK_FINISHED_ALERT))
465                                                        % get(a.handle)->name()
466                                                        % a.block_index
467                                                        % a.piece_index)
468                                )       );                             
469                        }
470                       
471                        void operator()(libt::block_downloading_alert const& a) const
472                        {
473                                event_log.post(shared_ptr<EventDetail>(
474                                        new EventGeneral(event_logger::debug, a.timestamp(),
475                                                wform(hal::app().res_wstr(HAL_BLOCK_DOWNLOADING_ALERT))
476                                                        % get(a.handle)->name()
477                                                        % a.block_index
478                                                        % a.piece_index)
479                                )       );                             
480                        }
481                       
482                        void operator()(libt::listen_failed_alert const& a) const
483                        {
484                                if (a.endpoint.address().is_v6())
485                                {       
486                                        event_log.post(shared_ptr<EventDetail>(
487                                                new EventGeneral(event_logger::info, a.timestamp(),
488                                                        hal::app().res_wstr(HAL_LISTEN_V6_FAILED_ALERT))
489                                        )       );             
490                                }
491                                else
492                                {
493                                        event_log.post(shared_ptr<EventDetail>(
494                                                new EventGeneral(event_logger::info, a.timestamp(),
495                                                        wform(hal::app().res_wstr(HAL_LISTEN_FAILED_ALERT))
496                                                                % hal::from_utf8_safe(a.msg()))
497                                        )       );
498                                }
499                        }
500                       
501                        void operator()(libt::listen_succeeded_alert const& a) const
502                        {
503                                event_log.post(shared_ptr<EventDetail>(
504                                        new EventGeneral(event_logger::info, a.timestamp(),
505                                                wform(hal::app().res_wstr(HAL_LISTEN_SUCCEEDED_ALERT))
506                                                        % hal::from_utf8_safe(a.msg()))
507                                )       );     
508
509                                bit_impl_.signals.successful_listen();
510                        }
511                       
512                        void operator()(libt::peer_blocked_alert const& a) const
513                        {
514                                event_log.post(shared_ptr<EventDetail>(
515                                        new EventGeneral(event_logger::debug, a.timestamp(),
516                                                wform(hal::app().res_wstr(HAL_IPFILTER_ALERT))
517                                                        % hal::from_utf8_safe(a.ip.to_string())
518                                                        % hal::from_utf8_safe(a.msg()))
519                                )       );                             
520                        }
521                       
522                        void operator()(libt::alert const& a) const
523                        {
524                                event_log.post(shared_ptr<EventDetail>(
525                                                new EventLibtorrent(lbtAlertToHalEvent(a.severity()), 
526                                                        a.timestamp(), event_logger::unclassified, hal::from_utf8_safe(a.msg()))));             
527                        }
528                       
529                        private:
530                                bit_impl& bit_impl_;
531                               
532                                torrent_internal_ptr get(libt::torrent_handle h) const 
533                                { 
534                                        return bit_impl_.theTorrents.get(from_utf8_safe(h.get_torrent_info().name())); 
535                                }
536                       
537                        } handler(*this);
538                       
539                        while (p_alert.get())
540                        {       
541                                try
542                                {
543                               
544                                libt::handle_alert<
545                                        libt::torrent_finished_alert,
546                                        libt::torrent_paused_alert,
547                                        libt::peer_error_alert,
548                                        libt::peer_ban_alert,
549                                        libt::hash_failed_alert,
550                                        libt::url_seed_alert,
551                                        libt::tracker_alert,
552                                        libt::tracker_warning_alert,
553                                        libt::tracker_announce_alert,
554                                        libt::tracker_reply_alert,
555                                        libt::fastresume_rejected_alert,
556                                        libt::piece_finished_alert,
557                                        libt::block_finished_alert,
558                                        libt::block_downloading_alert,
559                                        libt::listen_failed_alert,
560                                        libt::listen_succeeded_alert,
561                                        libt::peer_blocked_alert,
562                                        libt::alert
563                                >::handle_alert(p_alert, handler);                     
564                               
565                                }
566                                catch(libt::unhandled_alert&)
567                                {
568                                        handler(*p_alert);
569                                }
570                                catch(std::exception& e)
571                                {
572                                        // These are logged as debug because they are rarely important to act on!
573                                        event_log.post(shared_ptr<EventDetail>(\
574                                                new EventStdException(event_logger::debug, e, L"alertHandler")));
575                                }
576                               
577                                p_alert = theSession.pop_alert();
578                        }
579                       
580                        timer_.expires_from_now(boost::posix_time::seconds(2));
581                        timer_.async_wait(bind(&bit_impl::alertHandler, this));
582                        }
583
584                }
585                HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit_impl::alertHandler()")
586        }
587       
588        void saveTorrentData()
589        {       
590                mutex_t::scoped_lock l(mutex_);
591                try
592                {
593               
594                theTorrents.save_to_ini();
595                bittorrentIni.save_data();
596                       
597                if (dht_on_) 
598                {       
599                        halencode(workingDirectory/L"DHTState.bin", theSession.dht_state());
600                }
601               
602                }       
603                HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit_impl::saveTorrentData()")
604        }
605       
606        int defTorrentMaxConn() { return defTorrentMaxConn_; }
607        int defTorrentMaxUpload() { return defTorrentMaxUpload_; }
608        float defTorrentDownload() { return defTorrentDownload_; }
609        float defTorrentUpload() { return defTorrentUpload_; }
610       
611        const wpath workingDir() { return workingDirectory; };
612
613private:
614        bit_impl() :
615                theSession(libt::fingerprint(HALITE_FINGERPRINT)),
616                timer_(io_),
617                keepChecking_(false),
618                bittorrentIni(L"BitTorrent.xml"),
619                theTorrents(bittorrentIni),
620                defTorrentMaxConn_(-1),
621                defTorrentMaxUpload_(-1),
622                defTorrentDownload_(-1),
623                defTorrentUpload_(-1),
624                ip_filter_on_(false),
625                ip_filter_loaded_(false),
626                ip_filter_changed_(false),
627                ip_filter_count_(0),
628                dht_on_(false)
629        {
630                try
631                {
632                        torrent_internal::the_session_ = &theSession;
633                        torrent_internal::workingDir_ = workingDir();
634                       
635                        theSession.set_severity_level(libt::alert::debug);             
636                        theSession.add_extension(&libt::create_metadata_plugin);
637                        theSession.add_extension(&libt::create_ut_pex_plugin);
638                        theSession.set_max_half_open_connections(10);
639                       
640                        hal::event_log.post(shared_ptr<hal::EventDetail>(
641                                new hal::EventMsg(L"Loading BitTorrent.xml.", hal::event_logger::info)));               
642                        bittorrentIni.load_data();
643
644                        hal::event_log.post(shared_ptr<hal::EventDetail>(
645                                new hal::EventMsg(L"Loading torrent parameters.", hal::event_logger::info)));   
646                        theTorrents.load_from_ini();
647
648                        hal::event_log.post(shared_ptr<hal::EventDetail>(
649                                new hal::EventMsg(L"Loading done!", hal::event_logger::info)));
650                       
651                        try
652                        {                                               
653                        if (fs::exists(workingDirectory/L"Torrents.xml"))
654                        {
655                                {
656                                fs::wifstream ifs(workingDirectory/L"Torrents.xml");
657                       
658                                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Loading old Torrents.xml")));
659                       
660                                TorrentMap torrents;
661                                boost::archive::xml_wiarchive ia(ifs); 
662                                ia >> boost::serialization::make_nvp("torrents", torrents);
663                               
664                                theTorrents = torrents;
665                                }
666                               
667                                event_log.post(shared_ptr<EventDetail>(new EventMsg(
668                                        wform(L"Total %1%.") % theTorrents.size())));                           
669                               
670                                fs::rename(workingDirectory/L"Torrents.xml", workingDirectory/L"Torrents.xml.safe.to.delete");
671                        }                       
672                        }
673                        catch(const std::exception& e)
674                        {
675                                event_log.post(shared_ptr<EventDetail>(
676                                        new EventStdException(event_logger::fatal, e, L"Loading Old Torrents.xml")));
677                        }               
678                                       
679                        if (exists(workingDirectory/L"DHTState.bin"))
680                        {
681                                try
682                                {
683                                        dht_state_ = haldecode(workingDirectory/L"DHTState.bin");
684                                }               
685                                catch(const std::exception& e)
686                                {
687                                        event_log.post(shared_ptr<EventDetail>(
688                                                new EventStdException(event_logger::critical, e, L"Loading DHTState.bin")));
689                                }
690                        }
691                       
692                        {       libt::session_settings settings = theSession.settings();
693                                settings.user_agent = string("Halite ") + HALITE_VERSION_STRING;
694                                theSession.set_settings(settings);
695                        }
696                       
697                        timer_.expires_from_now(boost::posix_time::seconds(5));
698                        timer_.async_wait(bind(&bit_impl::alertHandler, this));
699                }
700                HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit_impl::bit_impl()")
701        }
702
703        bool create_torrent(const create_torrent_params& params, fs::wpath out_file, progress_callback fn)
704        {               
705        try
706        {
707                boost::intrusive_ptr<libt::torrent_info> t_info(new libt::torrent_info);
708
709                int piece_size = params.piece_size;
710                HAL_DEV_MSG(wform(L"piece size: %1%") % piece_size);
711                t_info->set_piece_size(piece_size);
712
713                HAL_DEV_MSG(L"Files");
714                for (file_size_pairs_t::const_iterator i = params.file_size_pairs.begin(), e = params.file_size_pairs.end();
715                                i != e; ++i)
716                {
717                        HAL_DEV_MSG(wform(L"file path: %1%, size: %2%") % (*i).first % (*i).second);
718                        t_info->add_file(to_utf8((*i).first.string()), (*i).second);
719                }
720
721                libt::file_pool f_pool;
722               
723                boost::scoped_ptr<libt::storage_interface> store(
724                        libt::default_storage_constructor(t_info, to_utf8(params.root_path.string()),
725                                f_pool));
726
727                HAL_DEV_MSG(L"Trackers");
728                for (tracker_details_t::const_iterator i = params.trackers.begin(), e = params.trackers.end();
729                                i != e; ++i)
730                {
731                        HAL_DEV_MSG(wform(L"URL: %1%, Tier: %2%") % (*i).url % (*i).tier);
732                        t_info->add_tracker(to_utf8((*i).url), (*i).tier);
733                }
734
735                HAL_DEV_MSG(L"Web Seeds");
736                for (web_seed_details_t::const_iterator i = params.web_seeds.begin(), e = params.web_seeds.end();
737                                i != e; ++i)
738                {
739                        HAL_DEV_MSG(wform(L"URL: %1%") % (*i).url);
740                        t_info->add_url_seed(to_utf8((*i).url));
741                }
742
743                HAL_DEV_MSG(L"DHT Nodes");
744                for (dht_node_details_t::const_iterator i = params.dht_nodes.begin(), e = params.dht_nodes.end();
745                                i != e; ++i)
746                {
747                        HAL_DEV_MSG(wform(L"URL: %1%, port: %2%") % (*i).url % (*i).port);
748                        t_info->add_node(hal::make_pair(to_utf8((*i).url), (*i).port));
749                }
750
751                // calculate the hash for all pieces
752                int num = t_info->num_pieces();
753                std::vector<char> piece_buf(piece_size);
754
755                for (int i = 0; i < num; ++i)
756                {
757                        store->read(&piece_buf[0], i, 0, t_info->piece_size(i));
758
759                        libt::hasher h(&piece_buf[0], t_info->piece_size(i));
760                        t_info->set_hash(i, h.final());
761
762                        if (fn(100*i / num, hal::app().res_wstr(HAL_NEWT_HASHING_PIECES)))
763                        {
764                                // User canceled torrent creation.
765
766                                hal::event_log.post(shared_ptr<hal::EventDetail>(
767                                        new hal::EventMsg(hal::app().res_wstr(HAL_NEWT_CREATION_CANCELED), hal::event_logger::info)));
768
769                                return true;
770                        }
771                }
772
773                t_info->set_creator(to_utf8(params.creator).c_str());
774                t_info->set_comment(to_utf8(params.comment).c_str());
775               
776                t_info->set_priv(params.private_torrent);
777
778                // create the torrent and print it to out
779                libt::entry e = t_info->create_torrent();
780                halencode(out_file, e);
781
782                }
783                HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit_impl::create_torrent()")
784
785                return false;
786        }
787       
788        std::pair<libt::entry, libt::entry> prepTorrent(wpath filename, wpath saveDirectory);
789        void removalThread(torrent_internal_ptr pIT, bool wipeFiles);
790       
791        libt::session theSession;       
792        mutable mutex_t mutex_;
793
794        asio::io_service io_;
795        asio::deadline_timer timer_;
796        bool keepChecking_;
797       
798        static wpath workingDirectory;
799        ini_file bittorrentIni;
800        TorrentManager theTorrents;     
801       
802        int defTorrentMaxConn_;
803        int defTorrentMaxUpload_;
804        float defTorrentDownload_;
805        float defTorrentUpload_;
806       
807        bool ip_filter_on_;
808        bool ip_filter_loaded_;
809        bool ip_filter_changed_;
810        libt::ip_filter ip_filter_;
811        size_t ip_filter_count_;
812       
813        void ip_filter_count();
814        void ip_filter_load(progress_callback fn);
815        void ip_filter_import(std::vector<libt::ip_range<asio::ip::address_v4> >& v4,
816                std::vector<libt::ip_range<asio::ip::address_v6> >& v6);
817       
818        bool dht_on_;
819        libt::dht_settings dht_settings_;
820        libt::entry dht_state_;
821       
822};
823
824wpath bit_impl::workingDirectory = hal::app().working_directory();
825
826bit::bit() :
827        pimpl(new bit_impl())
828{}
829
830#define HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH(FUNCTION) \
831catch (const libt::invalid_handle&) \
832{\
833        event_log.post(shared_ptr<EventDetail>( \
834                new EventInvalidTorrent(event_logger::critical, event_logger::invalidTorrent, name, std::string(FUNCTION)))); \
835}\
836catch (const invalidTorrent& t) \
837{\
838        event_log.post(shared_ptr<EventDetail>( \
839                new EventInvalidTorrent(event_logger::info, event_logger::invalidTorrent, t.who(), std::string(FUNCTION)))); \
840}\
841catch (const std::exception& e) \
842{\
843        event_log.post(shared_ptr<EventDetail>( \
844                new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), name, std::string(FUNCTION)))); \
845}
846
847#define HAL_GENERIC_TORRENT_EXCEPTION_CATCH(TORRENT, FUNCTION) \
848catch (const libt::invalid_handle&) \
849{\
850        event_log.post(shared_ptr<EventDetail>( \
851                new EventInvalidTorrent(event_logger::critical, event_logger::invalidTorrent, TORRENT, std::string(FUNCTION)))); \
852}\
853catch (const invalidTorrent& t) \
854{\
855        event_log.post(shared_ptr<EventDetail>( \
856                new EventInvalidTorrent(event_logger::info, event_logger::invalidTorrent, t.who(), std::string(FUNCTION)))); \
857}\
858catch (const std::exception& e) \
859{\
860        event_log.post(shared_ptr<EventDetail>( \
861                new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), TORRENT, std::string(FUNCTION)))); \
862}
863
864void bit::shutDownSession()
865{
866        pimpl.reset();
867}
868
869void bit::saveTorrentData()
870{
871        pimpl->saveTorrentData();
872}
873
874bool bit::create_torrent(const create_torrent_params& params, fs::wpath out_file, progress_callback fn)
875{
876        return pimpl->create_torrent(params, out_file, fn);
877}
878
879bit::torrent bit::get_wstr(const std::wstring& filename)
880{
881        return bit::torrent(pimpl->theTorrents.get(filename));
882}
883
884bool bit::listenOn(std::pair<int, int> const& range)
885{
886        try
887        {
888       
889        if (!pimpl->theSession.is_listening())
890        {
891                return pimpl->theSession.listen_on(range);
892        }
893        else
894        {
895                int port = pimpl->theSession.listen_port();
896               
897                if (port < range.first || port > range.second)
898                        return pimpl->theSession.listen_on(range);     
899                else
900                {
901                        pimpl->signals.successful_listen();
902                       
903                        return true;
904                }
905        }
906       
907        }
908        catch (const std::exception& e)
909        {
910                event_log.post(shared_ptr<EventDetail>(
911                        new EventStdException(event_logger::fatal, e, L"From bit::listenOn.")));
912
913                return false;
914        }
915        catch(...)
916        {
917                return false;
918        }
919}
920
921int bit::isListeningOn() 
922{
923        if (!pimpl->theSession.is_listening())
924                return -1;     
925        else
926                return pimpl->theSession.listen_port();
927}
928
929void bit::stopListening()
930{
931        ensureDhtOff();
932        pimpl->theSession.listen_on(std::make_pair(0, 0));
933}
934
935bool bit::ensureDhtOn()
936{
937        if (!pimpl->dht_on_)
938        {               
939                try
940                {
941                pimpl->theSession.start_dht(pimpl->dht_state_);
942                pimpl->dht_on_ = true;
943                }
944                catch(...)
945                {}
946        }
947                return pimpl->dht_on_;
948}
949
950void bit::ensureDhtOff()
951{
952        if (pimpl->dht_on_)
953        {
954                pimpl->theSession.stop_dht();           
955                pimpl->dht_on_ = false;
956        }
957}
958
959void bit::setDhtSettings(int max_peers_reply, int search_branching, 
960        int service_port, int max_fail_count)
961{
962        libt::dht_settings settings;
963        settings.max_peers_reply = max_peers_reply;
964        settings.search_branching = search_branching;
965        settings.service_port = service_port;
966        settings.max_fail_count = max_fail_count;
967       
968        if (pimpl->dht_settings_ != settings)
969        {
970                pimpl->dht_settings_ = settings;
971                pimpl->theSession.set_dht_settings(pimpl->dht_settings_);
972        }
973}
974
975void bit::setMapping(int mapping)
976{
977        if (mapping != mappingNone)
978        {
979                if (mapping == mappingUPnP)
980                {
981                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting UPnP mapping.")));
982                        pimpl->theSession.stop_upnp();
983                        pimpl->theSession.stop_natpmp();
984
985                        pimpl->signals.successful_listen.connect_once(bind(&libt::session::start_upnp, &pimpl->theSession));
986                }
987                else
988                {
989                        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting NAT-PMP mapping.")));
990                        pimpl->theSession.stop_upnp();
991                        pimpl->theSession.stop_natpmp();
992
993                        pimpl->signals.successful_listen.connect_once(bind(&libt::session::start_natpmp, &pimpl->theSession));
994                }
995        }
996        else
997        {
998                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"No mapping.")));
999                pimpl->theSession.stop_upnp();
1000                pimpl->theSession.stop_natpmp();
1001        }
1002}
1003
1004void bit::setTimeouts(int peers, int tracker)
1005{
1006        libt::session_settings settings = pimpl->theSession.settings();
1007        settings.peer_connect_timeout = peers;
1008        settings.tracker_completion_timeout = tracker;
1009
1010        pimpl->theSession.set_settings(settings);
1011
1012        event_log.post(shared_ptr<EventDetail>(new EventMsg(
1013                wform(L"Set Timeouts, peer %1%, tracker %2%") % peers % tracker)));
1014}
1015
1016void bit::setSessionLimits(int maxConn, int maxUpload)
1017{               
1018        pimpl->theSession.set_max_uploads(maxUpload);
1019        pimpl->theSession.set_max_connections(maxConn);
1020       
1021        event_log.post(shared_ptr<EventDetail>(new EventMsg(
1022                wform(L"Set connections totals %1% and uploads %2%.") 
1023                        % maxConn % maxUpload)));
1024}
1025
1026void bit::setSessionSpeed(float download, float upload)
1027{
1028        int down = (download > 0) ? static_cast<int>(download*1024) : -1;
1029        pimpl->theSession.set_download_rate_limit(down);
1030        int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
1031        pimpl->theSession.set_upload_rate_limit(up);
1032       
1033        event_log.post(shared_ptr<EventDetail>(new EventMsg(
1034                wform(L"Set session rates at download %1% and upload %2%.") 
1035                        % pimpl->theSession.download_rate_limit() % pimpl->theSession.upload_rate_limit())));
1036}
1037
1038void bit_impl::ip_filter_count()
1039{
1040        libt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();
1041       
1042        vectors.get<0>().erase(std::remove(vectors.get<0>().begin(), vectors.get<0>().end(), 0),
1043                vectors.get<0>().end());
1044        vectors.get<1>().erase(std::remove(vectors.get<1>().begin(), vectors.get<1>().end(), 0),
1045                vectors.get<1>().end());
1046        ip_filter_count_ = vectors.get<0>().size() + vectors.get<1>().size();
1047}
1048
1049void bit_impl::ip_filter_load(progress_callback fn)
1050{
1051        fs::ifstream ifs(workingDirectory/L"IPFilter.bin", std::ios::binary);
1052        if (ifs)
1053        {
1054                size_t v4_size;
1055                ifs >> v4_size;
1056               
1057                size_t total = v4_size/100;
1058                size_t previous = 0;
1059               
1060                for(unsigned i=0; i<v4_size; ++i)
1061                {
1062                        if (i-previous > total)
1063                        {
1064                                previous = i;
1065
1066                                if (fn) if (fn(size_t(i/total), hal::app().res_wstr(HAL_TORRENT_LOAD_FILTERS))) break;
1067                        }
1068                       
1069                        read_range_to_filter<asio::ip::address_v4>(ifs, ip_filter_);
1070                }
1071        }       
1072}
1073
1074void  bit_impl::ip_filter_import(std::vector<libt::ip_range<asio::ip::address_v4> >& v4,
1075        std::vector<libt::ip_range<asio::ip::address_v6> >& v6)
1076{
1077        for(std::vector<libt::ip_range<asio::ip::address_v4> >::iterator i=v4.begin();
1078                i != v4.end(); ++i)
1079        {
1080                ip_filter_.add_rule(i->first, i->last, libt::ip_filter::blocked);
1081        }
1082/*      for(std::vector<libt::ip_range<asio::ip::address_v6> >::iterator i=v6.begin();
1083                i != v6.end(); ++i)
1084        {
1085                ip_filter_.add_rule(i->first, i->last, libt::ip_filter::blocked);
1086        }
1087*/     
1088        /* Note here we do not set ip_filter_changed_ */
1089}
1090
1091bool bit::ensureIpFilterOn(progress_callback fn)
1092{
1093        try
1094        {
1095       
1096        if (!pimpl->ip_filter_loaded_)
1097        {
1098                pimpl->ip_filter_load(fn);
1099                pimpl->ip_filter_loaded_ = true;
1100        }
1101       
1102        if (!pimpl->ip_filter_on_)
1103        {
1104                pimpl->theSession.set_ip_filter(pimpl->ip_filter_);
1105                pimpl->ip_filter_on_ = true;
1106                pimpl->ip_filter_count();
1107        }
1108       
1109        }
1110        HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit::ensureIpFilterOn")
1111
1112        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters on.")));       
1113
1114        return false;
1115}
1116
1117void bit::ensureIpFilterOff()
1118{
1119        pimpl->theSession.set_ip_filter(libt::ip_filter());
1120        pimpl->ip_filter_on_ = false;
1121       
1122        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters off.")));     
1123}
1124
1125#ifndef TORRENT_DISABLE_ENCRYPTION     
1126void bit::ensurePeOn(int enc_level, int in_enc_policy, int out_enc_policy, bool prefer_rc4)
1127{
1128        libt::pe_settings pe;
1129       
1130        switch (enc_level)
1131        {
1132                case 0:
1133                        pe.allowed_enc_level = libt::pe_settings::plaintext;
1134                        break;
1135                case 1:
1136                        pe.allowed_enc_level = libt::pe_settings::rc4;
1137                        break;
1138                case 2:
1139                        pe.allowed_enc_level = libt::pe_settings::both;
1140                        break;
1141                default:
1142                        pe.allowed_enc_level = libt::pe_settings::both;
1143                       
1144                        hal::event_log.post(shared_ptr<hal::EventDetail>(
1145                                new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
1146                                        (wform(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % enc_level).str())));
1147        }
1148
1149        switch (in_enc_policy)
1150        {
1151                case 0:
1152                        pe.in_enc_policy = libt::pe_settings::forced;
1153                        break;
1154                case 1:
1155                        pe.in_enc_policy = libt::pe_settings::enabled;
1156                        break;
1157                case 2:
1158                        pe.in_enc_policy = libt::pe_settings::disabled;
1159                        break;
1160                default:
1161                        pe.in_enc_policy = libt::pe_settings::enabled;
1162                       
1163                        hal::event_log.post(shared_ptr<hal::EventDetail>(
1164                                new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
1165                                        (wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
1166        }
1167
1168        switch (out_enc_policy)
1169        {
1170                case 0:
1171                        pe.out_enc_policy = libt::pe_settings::forced;
1172                        break;
1173                case 1:
1174                        pe.out_enc_policy = libt::pe_settings::enabled;
1175                        break;
1176                case 2:
1177                        pe.out_enc_policy = libt::pe_settings::disabled;
1178                        break;
1179                default:
1180                        pe.out_enc_policy = libt::pe_settings::enabled;
1181                       
1182                        hal::event_log.post(shared_ptr<hal::EventDetail>(
1183                                new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, 
1184                                        (wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
1185        }
1186       
1187        pe.prefer_rc4 = prefer_rc4;
1188       
1189        try
1190        {
1191       
1192        pimpl->theSession.set_pe_settings(pe);
1193       
1194        }
1195        HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit::ensurePeOn")
1196       
1197        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption on.")));
1198}
1199
1200void bit::ensurePeOff()
1201{
1202        libt::pe_settings pe;
1203        pe.out_enc_policy = libt::pe_settings::disabled;
1204        pe.in_enc_policy = libt::pe_settings::disabled;
1205       
1206        pe.allowed_enc_level = libt::pe_settings::both;
1207        pe.prefer_rc4 = true;
1208       
1209        pimpl->theSession.set_pe_settings(pe);
1210
1211        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption off.")));
1212}
1213#endif
1214
1215void bit::ip_v4_filter_block(asio::ip::address_v4 first, asio::ip::address_v4 last)
1216{
1217        pimpl->ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
1218        pimpl->ip_filter_count();
1219        pimpl->ip_filter_changed_ = true;
1220}
1221
1222void bit::ip_v6_filter_block(asio::ip::address_v6 first, asio::ip::address_v6 last)
1223{
1224        pimpl->ip_filter_.add_rule(first, last, libt::ip_filter::blocked);
1225        pimpl->ip_filter_count();
1226        pimpl->ip_filter_changed_ = true;
1227}
1228
1229size_t bit::ip_filter_size()
1230{
1231        return pimpl->ip_filter_count_;
1232}
1233
1234void bit::clearIpFilter()
1235{
1236        pimpl->ip_filter_ = libt::ip_filter();
1237        pimpl->theSession.set_ip_filter(libt::ip_filter());     
1238        pimpl->ip_filter_changed_ = true;
1239        pimpl->ip_filter_count();
1240}
1241
1242bool bit::ip_filter_import_dat(boost::filesystem::path file, progress_callback fn, bool octalFix)
1243{
1244        try
1245        {
1246
1247        fs::ifstream ifs(file); 
1248        if (ifs)
1249        {
1250                boost::uintmax_t total = fs::file_size(file)/100;
1251                boost::uintmax_t progress = 0;
1252                boost::uintmax_t previous = 0;
1253               
1254                boost::regex reg("\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*-\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*.*");
1255                boost::regex ip_reg("0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)");
1256                boost::smatch m;
1257               
1258                string ip_address_line;         
1259                while (!std::getline(ifs, ip_address_line).eof())
1260                {               
1261                        progress += (ip_address_line.length() + 2);
1262                        if (progress-previous > total)
1263                        {
1264                                previous = progress;
1265                                if (fn)
1266                                {
1267                                        if (fn(size_t(progress/total), hal::app().res_wstr(HAL_TORRENT_IMPORT_FILTERS))) 
1268                                                break;
1269                                }
1270                        }
1271                       
1272                        if (boost::regex_match(ip_address_line, m, reg))
1273                        {
1274                                string first = m[1];
1275                                string last = m[2];
1276                               
1277                                if (octalFix)
1278                                {
1279                                        if (boost::regex_match(first, m, ip_reg))
1280                                        {
1281                                                first = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
1282                                                                ((m.length(2) != 0) ? m[2] : string("0")) + "." +
1283                                                                ((m.length(3) != 0) ? m[3] : string("0")) + "." +
1284                                                                ((m.length(4) != 0) ? m[4] : string("0"));
1285                                        }                                       
1286                                        if (boost::regex_match(last, m, ip_reg))
1287                                        {
1288                                                last = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
1289                                                           ((m.length(2) != 0) ? m[2] : string("0")) + "." +
1290                                                           ((m.length(3) != 0) ? m[3] : string("0")) + "." +
1291                                                           ((m.length(4) != 0) ? m[4] : string("0"));
1292                                        }
1293                                }
1294                               
1295                                try
1296                                {                       
1297                                pimpl->ip_filter_.add_rule(asio::ip::address_v4::from_string(first),
1298                                        asio::ip::address_v4::from_string(last), libt::ip_filter::blocked);     
1299                                }
1300                                catch(...)
1301                                {
1302                                        hal::event_log.post(shared_ptr<hal::EventDetail>(
1303                                                new hal::EventDebug(hal::event_logger::info, 
1304                                                from_utf8((boost::format("Invalid IP range: %1%-%2%.") % first % last).str()))));
1305                                }
1306                        }
1307                }
1308        }
1309       
1310        pimpl->ip_filter_changed_ = true;
1311        pimpl->ip_filter_count();
1312       
1313        }
1314        HAL_GENERIC_FN_EXCEPTION_CATCH(L"bit::ip_filter_import_dat()")
1315
1316        return false;
1317}
1318
1319const SessionDetail bit::getSessionDetails()
1320{
1321        SessionDetail details;
1322       
1323        details.port = pimpl->theSession.is_listening() ? pimpl->theSession.listen_port() : -1;
1324       
1325        libt::session_status status = pimpl->theSession.status();
1326       
1327        details.speed = std::pair<double, double>(status.download_rate, status.upload_rate);
1328       
1329        details.dht_on = pimpl->dht_on_;
1330        details.dht_nodes = status.dht_nodes;
1331        details.dht_torrents = status.dht_torrents;
1332       
1333        details.ip_filter_on = pimpl->ip_filter_on_;
1334        details.ip_ranges_filtered = pimpl->ip_filter_count_;
1335       
1336        return details;
1337}
1338
1339void bit::setSessionHalfOpenLimit(int halfConn)
1340{
1341        pimpl->theSession.set_max_half_open_connections(halfConn);
1342
1343        event_log.post(shared_ptr<EventDetail>(new EventMsg(
1344                wform(L"Set half-open connections limit to %1%.") % pimpl->theSession.max_half_open_connections())));
1345}
1346
1347void bit::setTorrentDefaults(int maxConn, int maxUpload, float download, float upload)
1348{
1349        pimpl->defTorrentMaxConn_ = maxConn;
1350        pimpl->defTorrentMaxUpload_ = maxUpload;
1351
1352        event_log.post(shared_ptr<EventDetail>(new EventMsg(
1353                wform(L"Set torrent connections total %1% and uploads %2%.") % maxConn % maxUpload)));
1354
1355        pimpl->defTorrentDownload_ = download;
1356        pimpl->defTorrentUpload_ = upload;
1357
1358        event_log.post(shared_ptr<EventDetail>(new EventMsg(
1359                wform(L"Set torrent default rates at %1$.2fkb/s down and %2$.2fkb/s upload.") % download % upload)));
1360}
1361
1362std::pair<libt::entry, libt::entry> bit_impl::prepTorrent(wpath filename, wpath saveDirectory)
1363{
1364        libt::entry metadata = haldecode(filename);
1365        libt::torrent_info info(metadata);
1366       
1367        wstring torrentName = hal::from_utf8_safe(info.name());
1368        if (!boost::find_last(torrentName, L".torrent")) 
1369                torrentName += L".torrent";
1370       
1371        wpath torrentFilename = torrentName;
1372        const wpath resumeFile = workingDirectory/L"resume"/torrentFilename.leaf();
1373       
1374        //  vvv Handle old naming style!
1375        const wpath oldResumeFile = workingDirectory/L"resume"/filename.leaf();
1376       
1377        if (filename.leaf() != torrentFilename.leaf() && exists(oldResumeFile))
1378                fs::rename(oldResumeFile, resumeFile);
1379        //  ^^^ Handle old naming style!       
1380       
1381        libt::entry resumeData; 
1382       
1383        if (fs::exists(resumeFile)) 
1384        {
1385                try 
1386                {
1387                        resumeData = haldecode(resumeFile);
1388                }
1389                catch(std::exception &e) 
1390                {               
1391                        hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
1392                                new hal::EventStdException(event_logger::critical, e, L"prepTorrent, Resume"))); 
1393       
1394                        fs::remove(resumeFile);
1395                }
1396        }
1397
1398        if (!fs::exists(workingDirectory/L"torrents"))
1399                fs::create_directory(workingDirectory/L"torrents");
1400
1401        if (!fs::exists(workingDirectory/L"torrents"/torrentFilename.leaf()))
1402                fs::copy_file(filename.string(), workingDirectory/L"torrents"/torrentFilename.leaf());
1403
1404        if (!fs::exists(saveDirectory))
1405                fs::create_directory(saveDirectory);
1406       
1407        return std::make_pair(metadata, resumeData);
1408}
1409
1410void bit::addTorrent(wpath file, wpath saveDirectory, bool startStopped, bool compactStorage, 
1411                boost::filesystem::wpath moveToDirectory, bool useMoveTo) 
1412{
1413        try 
1414        {       
1415        torrent_internal_ptr TIp;
1416
1417        std::pair<std::string, std::string> names = extract_names(file);
1418        wstring xml_name = from_utf8(names.first) + L".xml";
1419
1420        // Commented out purposely!
1421        if (false && fs::exists(file.branch_path()/xml_name))
1422        {
1423                torrent_standalone tsa;
1424               
1425                if (tsa.load_standalone(file.branch_path()/xml_name))
1426                {
1427                        TIp = tsa.torrent;
1428                       
1429                        TIp->set_save_directory(saveDirectory, true);                   
1430                        if (useMoveTo)
1431                                TIp->set_move_to_directory(moveToDirectory);
1432
1433                        TIp->prepare(file);
1434                }
1435        }
1436
1437        if (!TIp)
1438        {
1439                if (useMoveTo)
1440                        TIp.reset(new torrent_internal(file, saveDirectory, compactStorage, moveToDirectory));         
1441                else
1442                        TIp.reset(new torrent_internal(file, saveDirectory, compactStorage));
1443
1444                TIp->setTransferSpeed(bittorrent().defTorrentDownload(), bittorrent().defTorrentUpload());
1445                TIp->setConnectionLimit(bittorrent().defTorrentMaxConn(), bittorrent().defTorrentMaxUpload());
1446        }
1447       
1448        std::pair<TorrentManager::torrentByName::iterator, bool> p =
1449                pimpl->theTorrents.insert(TIp);
1450       
1451        if (p.second)
1452        {
1453                torrent_internal_ptr me = pimpl->theTorrents.get(TIp->name());         
1454               
1455                if (!startStopped) 
1456                        me->add_to_session();
1457                else
1458                        me->set_state_stopped();
1459        }
1460       
1461        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(to_utf8(file.string()), "addTorrent")
1462}
1463
1464const TorrentDetails& bit::torrentDetails()
1465{
1466        return torrentDetails_;
1467}
1468
1469const TorrentDetails& bit::updateTorrentDetails(const wstring& focused, const std::set<wstring>& selected)
1470{
1471        try {
1472       
1473        mutex_t::scoped_lock l(torrentDetails_.mutex_); 
1474       
1475        torrentDetails_.clearAll(l);   
1476        torrentDetails_.torrents_.reserve(pimpl->theTorrents.size());
1477       
1478        for (TorrentManager::torrentByName::iterator i=pimpl->theTorrents.begin(), e=pimpl->theTorrents.end(); i != e; ++i)
1479        {
1480                wstring utf8Name = (*i).torrent->name();
1481                TorrentDetail_ptr pT = (*i).torrent->getTorrentDetail_ptr();
1482               
1483                if (selected.find(utf8Name) != selected.end())
1484                {
1485                        torrentDetails_.selectedTorrents_.push_back(pT);
1486                }
1487               
1488                if (focused == utf8Name)
1489                        torrentDetails_.selectedTorrent_ = pT;
1490               
1491                torrentDetails_.torrentMap_[(*i).torrent->name()] = pT;
1492                torrentDetails_.torrents_.push_back(pT);
1493        }
1494       
1495        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "updateTorrentDetails")
1496       
1497        return torrentDetails_;
1498}
1499
1500void bit::resumeAll()
1501{
1502        try {
1503               
1504        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Resuming torrent.")));
1505       
1506        for (TorrentManager::torrentByName::iterator i=pimpl->theTorrents.begin(), e=pimpl->theTorrents.end(); i != e;)
1507        {
1508                wpath file = wpath(pimpl->workingDirectory)/L"torrents"/(*i).torrent->filename();
1509               
1510                if (exists(file))
1511                {               
1512                        try 
1513                        {
1514                               
1515                        (*i).torrent->prepare(file);   
1516
1517                        switch ((*i).torrent->state())
1518                        {
1519                                case TorrentDetail::torrent_stopped:
1520                                        break;
1521                                case TorrentDetail::torrent_paused:
1522                                        (*i).torrent->add_to_session(true);
1523                                        break;
1524                                case TorrentDetail::torrent_active:
1525                                        (*i).torrent->add_to_session(false);
1526                                        break;
1527                                default:
1528                                        assert(false);
1529                        };
1530                       
1531                        ++i;
1532                       
1533                        }
1534                        catch(const libt::duplicate_torrent&)
1535                        {
1536                                hal::event_log.post(shared_ptr<hal::EventDetail>(
1537                                        new hal::EventDebug(hal::event_logger::debug, L"Encountered duplicate torrent")));
1538                               
1539                                ++i; // Harmless, don't worry about it.
1540                        }
1541                        catch(const std::exception& e) 
1542                        {
1543                                hal::event_log.post(shared_ptr<hal::EventDetail>(
1544                                        new hal::EventStdException(hal::event_logger::warning, e, L"resumeAll")));
1545                               
1546                                pimpl->theTorrents.erase(i++);
1547                        }                       
1548                }
1549                else
1550                {
1551                        pimpl->theTorrents.erase(i++);
1552                }
1553        }
1554       
1555        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "resumeAll")
1556}
1557
1558void bit::closeAll(boost::optional<report_num_active> fn)
1559{
1560        try 
1561        {       
1562        event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Saving torrent data...")));
1563
1564        pimpl->saveTorrentData();
1565
1566        event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Stopping all torrents...")));
1567       
1568        for (TorrentManager::torrentByName::iterator i=pimpl->theTorrents.begin(), e=pimpl->theTorrents.end(); 
1569                i != e; ++i)
1570        {
1571                (*i).torrent->stop();
1572        }
1573       
1574        // Ok this polling loop here is a bit curde, but a blocking wait is actually appropiate.
1575        for (int num_active = -1; num_active != 0; )
1576        {
1577                num_active = 0;
1578
1579                for (TorrentManager::torrentByName::iterator i=pimpl->theTorrents.begin(), e=pimpl->theTorrents.end(); 
1580                                i != e; ++i)
1581                {
1582                        if ((*i).torrent->state() != TorrentDetail::torrent_stopped)
1583                                ++num_active;
1584                }
1585               
1586                event_log.post(shared_ptr<EventDetail>(new EventInfo(wform(L"%1% still active") % num_active)));
1587
1588                if (fn) (*fn)(num_active);
1589                Sleep(200);
1590        }
1591       
1592        event_log.post(shared_ptr<EventDetail>(new EventInfo(L"All torrents stopped.")));               
1593        event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Fast-resume data written.")));
1594       
1595        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll")
1596}
1597
1598PeerDetail::PeerDetail(libt::peer_info& peerInfo) :
1599        ipAddress(hal::from_utf8_safe(peerInfo.ip.address().to_string())),
1600        country(L""),
1601        speed(std::make_pair(peerInfo.payload_down_speed, peerInfo.payload_up_speed)),
1602        client(hal::from_utf8_safe(peerInfo.client))
1603{
1604        std::vector<wstring> status_vec;
1605       
1606#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
1607        if (peerInfo.country[0] != 0 && peerInfo.country[1] != 0)
1608                country = (wform(L"(%1%)") % hal::from_utf8_safe(string(peerInfo.country, 2))).str().c_str();
1609#endif 
1610
1611        if (peerInfo.flags & libt::peer_info::handshake)
1612        {
1613                status_vec.push_back(app().res_wstr(HAL_PEER_HANDSHAKE));
1614        }               
1615        else if (peerInfo.flags & libt::peer_info::connecting)
1616        {
1617                status_vec.push_back(app().res_wstr(HAL_PEER_CONNECTING));
1618        }
1619        else
1620        {
1621        #ifndef TORRENT_DISABLE_ENCRYPTION             
1622                if (peerInfo.flags & libt::peer_info::rc4_encrypted)
1623                        status_vec.push_back(app().res_wstr(HAL_PEER_RC4_ENCRYPTED));           
1624                if (peerInfo.flags & libt::peer_info::plaintext_encrypted)
1625                        status_vec.push_back(app().res_wstr(HAL_PEER_PLAINTEXT_ENCRYPTED));
1626        #endif
1627               
1628                if (peerInfo.flags & libt::peer_info::interesting)
1629                        status_vec.push_back(app().res_wstr(HAL_PEER_INTERESTING));     
1630                if (peerInfo.flags & libt::peer_info::choked)
1631                        status_vec.push_back(app().res_wstr(HAL_PEER_CHOKED)); 
1632                if (peerInfo.flags & libt::peer_info::remote_interested)
1633                        status_vec.push_back(app().res_wstr(HAL_PEER_REMOTE_INTERESTING));     
1634                if (peerInfo.flags & libt::peer_info::remote_choked)
1635                        status_vec.push_back(app().res_wstr(HAL_PEER_REMOTE_CHOKED));   
1636                if (peerInfo.flags & libt::peer_info::supports_extensions)
1637                        status_vec.push_back(app().res_wstr(HAL_PEER_SUPPORT_EXTENSIONS));     
1638        //      if (peerInfo.flags & libt::peer_info::local_connection)                                         // Not sure whats up here?
1639        //              status_vec.push_back(app().res_wstr(HAL_PEER_LOCAL_CONNECTION));                       
1640                if (peerInfo.flags & libt::peer_info::queued)
1641                        status_vec.push_back(app().res_wstr(HAL_PEER_QUEUED));
1642        }
1643       
1644        seed = (peerInfo.flags & libt::peer_info::seed) ? true : false;
1645       
1646        if (!status_vec.empty()) status = status_vec[0];
1647       
1648        if (status_vec.size() > 1)
1649        {
1650                for (size_t i=1; i<status_vec.size(); ++i)
1651                {
1652                        status += L"; ";
1653                        status += status_vec[i];
1654                }
1655        }       
1656}
1657
1658void bit::getAllPeerDetails(const std::string& filename, PeerDetails& peerContainer)
1659{
1660        getAllPeerDetails(from_utf8_safe(filename), peerContainer);
1661}
1662
1663void bit::getAllPeerDetails(const std::wstring& filename, PeerDetails& peerContainer)
1664{
1665        try {
1666       
1667        pimpl->theTorrents.get(filename)->getPeerDetails(peerContainer);
1668       
1669        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getAllPeerDetails")
1670}
1671
1672void bit::getAllFileDetails(const std::string& filename, FileDetails& fileDetails)
1673{
1674        getAllFileDetails(from_utf8_safe(filename), fileDetails);
1675}
1676
1677void bit::getAllFileDetails(const std::wstring& filename, FileDetails& fileDetails)
1678{
1679        try {
1680       
1681        pimpl->theTorrents.get(filename)->getFileDetails(fileDetails);
1682       
1683        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getAllFileDetails")
1684}
1685
1686bool bit::isTorrent(const std::string& filename)
1687{       
1688        return isTorrent(hal::to_wstr_shim(filename));
1689}
1690
1691bool bit::isTorrent(const std::wstring& filename)
1692{       
1693        try {
1694       
1695        return pimpl->theTorrents.exists(filename);
1696       
1697        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "isTorrent")
1698       
1699        return false;
1700}
1701
1702void bit::pauseTorrent(const std::string& filename)
1703{
1704        pauseTorrent(hal::to_wstr_shim(filename));
1705}
1706
1707void bit::pauseTorrent(const std::wstring& filename)
1708{
1709        try {
1710       
1711        pimpl->theTorrents.get(filename)->pause();
1712       
1713        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "pauseTorrent")
1714}
1715
1716void bit::resumeTorrent(const std::string& filename)
1717{
1718        resumeTorrent(hal::to_wstr_shim(filename));
1719}
1720
1721void bit::resumeTorrent(const std::wstring& filename)
1722{
1723        try {
1724       
1725        pimpl->theTorrents.get(filename)->resume();
1726       
1727        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "resumeTorrent")
1728}
1729
1730void bit::stopTorrent(const std::string& filename)
1731{
1732        stopTorrent(hal::to_wstr_shim(filename));
1733}
1734
1735void bit::stopTorrent(const std::wstring& filename)
1736{
1737        try {
1738       
1739        pimpl->theTorrents.get(filename)->stop();
1740       
1741        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "stopTorrent")
1742}
1743
1744bool bit::isTorrentActive(const std::string& filename)
1745{
1746        return isTorrentActive(hal::to_wstr_shim(filename));
1747}
1748
1749bool bit::isTorrentActive(const std::wstring& filename)
1750{
1751        try {
1752       
1753        return pimpl->theTorrents.get(filename)->is_active();
1754       
1755        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "isTorrentActive")
1756       
1757        return false; // ??? is this correct
1758}
1759
1760void bit::reannounceTorrent(const std::string& filename)
1761{
1762        reannounceTorrent(hal::to_wstr_shim(filename));
1763}
1764
1765void bit::reannounceTorrent(const std::wstring& filename)
1766{
1767        try {
1768       
1769        pimpl->theTorrents.get(filename)->handle().force_reannounce();
1770       
1771        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "reannounceTorrent")
1772}
1773
1774void bit_impl::removalThread(torrent_internal_ptr pIT, bool wipeFiles)
1775{
1776        try {
1777
1778        if (!wipeFiles)
1779        {
1780                theSession.remove_torrent(pIT->handle());
1781        }
1782        else
1783        {
1784                if (pIT->in_session())
1785                {
1786                        theSession.remove_torrent(pIT->handle(), libt::session::delete_files);
1787                }
1788                else
1789                {
1790                        libt::torrent_info m_info = pIT->infoMemory();
1791                       
1792                        // delete the files from disk
1793                        std::string error;
1794                        std::set<std::string> directories;
1795                       
1796                        for (libt::torrent_info::file_iterator i = m_info.begin_files(true)
1797                                , end(m_info.end_files(true)); i != end; ++i)
1798                        {
1799                                std::string p = (hal::path_to_utf8(pIT->saveDirectory()) / i->path).string();
1800                                fs::path bp = i->path.branch_path();
1801                               
1802                                std::pair<std::set<std::string>::iterator, bool> ret;
1803                                ret.second = true;
1804                                while (ret.second && !bp.empty())
1805                                {
1806                                        std::pair<std::set<std::string>::iterator, bool> ret = 
1807                                                directories.insert((hal::path_to_utf8(pIT->saveDirectory()) / bp).string());
1808                                        bp = bp.branch_path();
1809                                }
1810                                if (!fs::remove(hal::from_utf8(p).c_str()) && errno != ENOENT)
1811                                        error = std::strerror(errno);
1812                        }
1813
1814                        // remove the directories. Reverse order to delete subdirectories first
1815
1816                        for (std::set<std::string>::reverse_iterator i = directories.rbegin()
1817                                , end(directories.rend()); i != end; ++i)
1818                        {
1819                                if (!fs::remove(hal::from_utf8(*i).c_str()) && errno != ENOENT)
1820                                        error = std::strerror(errno);
1821                        }
1822                }
1823        }
1824
1825        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "removalThread")
1826}
1827
1828void bit::removeTorrent(const std::string& filename)
1829{
1830        removeTorrent(hal::to_wstr_shim(filename));
1831}
1832
1833void bit::removeTorrent(const std::wstring& filename)
1834{
1835        try {
1836       
1837        torrent_internal_ptr pTI = pimpl->theTorrents.get(filename);
1838        libt::torrent_handle handle = pTI->handle();
1839        pimpl->theTorrents.erase(filename);
1840       
1841        thread_t t(bind(&bit_impl::removalThread, &*pimpl, pTI, false));       
1842       
1843        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "removeTorrent")
1844}
1845
1846void bit::recheckTorrent(const std::string& filename)
1847{
1848        recheckTorrent(hal::to_wstr_shim(filename));
1849}
1850
1851void bit::recheckTorrent(const std::wstring& filename)
1852{
1853        try {
1854       
1855        pimpl->theTorrents.get(filename)->force_recheck();
1856       
1857        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "recheckTorrent")
1858}
1859
1860void bit::removeTorrentWipeFiles(const std::string& filename)
1861{
1862        removeTorrentWipeFiles(hal::to_wstr_shim(filename));
1863}
1864
1865void bit::removeTorrentWipeFiles(const std::wstring& filename)
1866{
1867        try {
1868       
1869        torrent_internal_ptr pTI = pimpl->theTorrents.get(filename);
1870        libt::torrent_handle handle = pTI->handle();
1871        pimpl->theTorrents.erase(filename);
1872       
1873        thread_t t(bind(&bit_impl::removalThread, &*pimpl, pTI, true)); 
1874       
1875        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "removeTorrentWipeFiles")
1876}
1877
1878void bit::pauseAllTorrents()
1879{       
1880        try {
1881       
1882        for (TorrentManager::torrentByName::iterator i=pimpl->theTorrents.begin(), e=pimpl->theTorrents.end();
1883                i != e; ++i)
1884        {               
1885                if ((*i).torrent->in_session())
1886                        (*i).torrent->pause();
1887        }
1888       
1889        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "pauseAllTorrents")
1890}
1891
1892void bit::unpauseAllTorrents()
1893{       
1894        try {
1895       
1896        for (TorrentManager::torrentByName::iterator i=pimpl->theTorrents.begin(), e=pimpl->theTorrents.end();
1897                i != e; ++i)
1898        {
1899                if ((*i).torrent->in_session() && (*i).torrent->state() == TorrentDetail::torrent_paused)
1900                        (*i).torrent->resume();
1901        }
1902       
1903        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "unpauseAllTorrents")
1904}
1905
1906bit::torrent::torrent()
1907{}
1908
1909bit::torrent::torrent(boost::shared_ptr<torrent_internal> p) :
1910        ptr(p)
1911{}
1912
1913bool bit::torrent::is_open() const
1914{
1915        return ptr;
1916}
1917
1918bit::torrent::exec_around_ptr::proxy::proxy(torrent_internal* t) : 
1919        t_(t),
1920        l_(t->mutex_)
1921{
1922        HAL_DEV_MSG(L"Ctor proxy");
1923}
1924
1925bit::torrent::exec_around_ptr::proxy::~proxy() 
1926{
1927        HAL_DEV_MSG(L"Dtor proxy");
1928}
1929
1930const std::wstring bit::torrent::get_name() const
1931{
1932        try {
1933       
1934        return ptr->name();
1935       
1936        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(L"Torrent Unknown", "torrent::get_name()")
1937       
1938        return 0;
1939}
1940
1941float bit::torrent::get_ratio() const
1942{
1943        try {
1944       
1945        return ptr->get_ratio();
1946       
1947        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_ratio")
1948       
1949        return 0;
1950}
1951
1952void bit::torrent::set_ratio(float r)
1953{
1954        try {
1955
1956        ptr->set_ratio(r);
1957       
1958        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_ratio")
1959}
1960
1961std::pair<int, int> bit::torrent::get_connection_limits() const
1962{
1963        try {
1964       
1965        return ptr->getConnectionLimit();
1966       
1967        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_connection_limits")
1968       
1969        return std::make_pair(-1, -1);
1970}
1971
1972void bit::torrent::set_connection_limits(const std::pair<int, int>& l)
1973{
1974        try {
1975       
1976        ptr->setConnectionLimit(l.first, l.second);
1977       
1978        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_connection_limits")
1979}
1980
1981std::pair<float, float> bit::torrent::get_rate_limits() const
1982{
1983        try {
1984       
1985        return ptr->getTransferSpeed();
1986       
1987        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_rate_limits")
1988       
1989        return std::pair<float, float>(-1.0, -1.0);
1990}
1991
1992void bit::torrent::set_rate_limits(const std::pair<float, float>& l)
1993{
1994        try {
1995       
1996        ptr->setTransferSpeed(l.first, l.second);
1997       
1998        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_rate_limits")
1999}
2000
2001wpath bit::torrent::get_save_directory() const
2002{
2003        try {
2004       
2005        return ptr->get_save_directory();
2006       
2007        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_save_directory")
2008       
2009        return L"";
2010}
2011
2012void bit::torrent::set_save_directory(const wpath& s)
2013{
2014        try {
2015       
2016        ptr->set_save_directory(s);
2017       
2018        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_save_directory")
2019}
2020
2021wpath bit::torrent::get_move_to_directory() const
2022{
2023        try {
2024       
2025        return ptr->get_move_to_directory();
2026       
2027        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_save_directory")
2028       
2029        return L"";
2030}
2031
2032void bit::torrent::set_move_to_directory(const wpath& m)
2033{
2034        try {
2035       
2036        ptr->set_move_to_directory(m);
2037       
2038        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_move_to_directory")
2039}
2040
2041std::pair<wstring, wstring> bit::torrent::get_tracker_login() const
2042{
2043        try {
2044       
2045        return ptr->getTrackerLogin();
2046       
2047        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("get_tracker_login")
2048       
2049        return std::make_pair(L"!!! exception thrown !!!", L"!!! exception thrown !!!");
2050}
2051
2052void bit::torrent::set_tracker_login(const std::pair<wstring, wstring>& p)
2053{
2054        try {
2055       
2056        ptr->setTrackerLogin(p.first, p.second);
2057       
2058        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_tracker_login")
2059}
2060
2061bool bit::torrent::get_is_active() const
2062{
2063        try {
2064       
2065        return ptr->is_active();
2066       
2067        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_is_active")
2068       
2069        return L"";
2070}
2071
2072bool bit::torrent::get_in_session() const
2073{
2074        try {
2075       
2076        return ptr->in_session();
2077       
2078        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_in_session")
2079       
2080        return L"";
2081}
2082
2083std::vector<tracker_detail> bit::torrent::get_trackers() const
2084{
2085        try {
2086       
2087        return ptr->getTrackers();
2088       
2089        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::get_trackers")
2090       
2091        return std::vector<tracker_detail>();
2092}
2093
2094void bit::torrent::set_trackers(const std::vector<tracker_detail>& trackers)
2095{
2096        try {
2097       
2098        ptr->setTrackers(trackers);
2099       
2100        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_trackers")
2101}
2102
2103void bit::torrent::reset_trackers()
2104{
2105        try {
2106       
2107        ptr->resetTrackers();
2108       
2109        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_trackers")
2110}
2111
2112void bit::torrent::set_file_priorities(const std::pair<std::vector<int>, int>& p)
2113{
2114        try { 
2115
2116        ptr->setFilePriorities(p.first, p.second);
2117       
2118        } HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH("torrent::set_trackers")
2119}
2120
2121void bit::startEventReceiver()
2122{
2123        pimpl->keepChecking_ = true;
2124        thread_t(bind(&asio::io_service::run, &pimpl->io_));
2125}
2126
2127void bit::stopEventReceiver()
2128{
2129        event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Stopping event Handler.")));
2130
2131        pimpl->stopAlertHandler();
2132}
2133
2134int bit::defTorrentMaxConn() { return pimpl->defTorrentMaxConn_; }
2135int bit::defTorrentMaxUpload() { return pimpl->defTorrentMaxUpload_; }
2136float bit::defTorrentDownload() { return pimpl->defTorrentDownload_; }
2137float bit::defTorrentUpload() { return pimpl->defTorrentUpload_; }
2138       
2139};
Note: See TracBrowser for help on using the repository browser.