source: trunk/src/halTorrent.cpp @ 457

Revision 457, 57.7 KB checked in by Eoin, 12 years ago (diff)

Cleaned orphaned code.

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