source: src/halTorrent.cpp @ 237

Revision 237, 39.2 KB checked in by Eoin, 13 years ago (diff)
Line 
1
2#include "stdAfx.hpp"
3
4#include <iostream>
5#include <fstream>
6#include <iterator>
7#include <iomanip>
8#include <map>
9#include <algorithm>
10#include <string>
11#include <vector>
12
13#include <boost/foreach.hpp>
14#include <boost/bind.hpp>
15#include <boost/array.hpp>
16#include <boost/regex.hpp>
17#include <boost/lambda/lambda.hpp>
18#include <boost/archive/text_woarchive.hpp>
19#include <boost/archive/text_wiarchive.hpp>
20#include <boost/archive/binary_woarchive.hpp>
21#include <boost/archive/binary_wiarchive.hpp>
22#include <boost/archive/text_oarchive.hpp>
23#include <boost/archive/text_iarchive.hpp>
24#include <boost/archive/binary_oarchive.hpp>
25#include <boost/archive/binary_iarchive.hpp>
26#include <boost/archive/xml_woarchive.hpp>
27#include <boost/archive/xml_wiarchive.hpp>
28#include <boost/archive/xml_oarchive.hpp>
29#include <boost/archive/xml_iarchive.hpp>
30#include <boost/serialization/version.hpp>
31#include <boost/serialization/vector.hpp>
32#include <boost/serialization/map.hpp>
33#include <boost/serialization/split_free.hpp>
34
35#include <libtorrent/file.hpp>
36#include <libtorrent/hasher.hpp>
37#include <libtorrent/alert_types.hpp>
38#include <libtorrent/entry.hpp>
39#include <libtorrent/bencode.hpp>
40#include <libtorrent/session.hpp>
41#include <libtorrent/ip_filter.hpp>
42#include <libtorrent/torrent_handle.hpp>
43#include <libtorrent/peer_connection.hpp>
44#include <libtorrent/extensions/metadata_transfer.hpp>
45#include <libtorrent/extensions/ut_pex.hpp>
46
47#include "halTorrent.hpp"
48#include "halEvent.hpp"
49#include "global/string_conv.hpp"
50
51#define foreach BOOST_FOREACH
52
53namespace boost {
54namespace serialization {
55
56#define IP_SAVE  3
57
58template<class Archive, class address_type>
59void save(Archive& ar, const address_type& ip, const unsigned int version)
60{       
61#if IP_SAVE == 1
62        typename address_type::bytes_type bytes = ip.to_bytes();       
63        for (typename address_type::bytes_type::iterator i=bytes.begin(); i != bytes.end(); ++i)
64                ar & BOOST_SERIALIZATION_NVP(*i);
65#elif IP_SAVE == 2
66        string dotted = ip.to_string(); 
67        ar & BOOST_SERIALIZATION_NVP(dotted);
68#elif IP_SAVE == 3
69        unsigned long addr = ip.to_ulong();     
70        ar & BOOST_SERIALIZATION_NVP(addr);
71#endif
72}
73
74template<class Archive, class address_type>
75void load(Archive& ar, address_type& ip, const unsigned int version)
76{       
77#if IP_SAVE == 1
78        typename address_type::bytes_type bytes;       
79        for (typename address_type::bytes_type::iterator i=bytes.begin(); i != bytes.end(); ++i)
80                ar & BOOST_SERIALIZATION_NVP(*i);       
81        ip = address_type(bytes);
82#elif IP_SAVE == 2     
83        string dotted;
84        ar & BOOST_SERIALIZATION_NVP(dotted);   
85        ip = address_type::from_string(dotted);
86#elif IP_SAVE == 3
87        unsigned long addr;
88        ar & BOOST_SERIALIZATION_NVP(addr);     
89        ip = address_type(addr);
90#endif
91}
92
93template<class Archive, class address_type>
94void serialize(Archive& ar, libtorrent::ip_range<address_type>& addr, const unsigned int version)
95{       
96        ar & BOOST_SERIALIZATION_NVP(addr.first);
97        ar & BOOST_SERIALIZATION_NVP(addr.last);
98        addr.flags = libtorrent::ip_filter::blocked;
99}
100
101template<class Archive>
102void serialize(Archive& ar, hal::TrackerDetail& tracker, const unsigned int version)
103{       
104        ar & BOOST_SERIALIZATION_NVP(tracker.url);
105        ar & BOOST_SERIALIZATION_NVP(tracker.tier);
106}
107
108} // namespace serialization
109} // namespace boost
110
111BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v4)
112BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v6)
113
114namespace libtorrent
115{
116template<class Addr>
117bool operator==(const libtorrent::ip_range<Addr>& lhs, const int flags)
118{
119        return (lhs.flags == flags);
120}
121
122std::ostream& operator<<(std::ostream& os, libtorrent::ip_range<asio::ip::address_v4>& ip)
123{
124        os << ip.first.to_ulong();
125        os << ip.last.to_ulong();
126       
127        return os;
128}
129
130} // namespace libtorrent
131
132
133#include "halTorrentInternal.hpp"
134
135namespace hal
136{
137        libtorrent::session* TorrentInternal::the_session_ = 0;
138}
139
140namespace hal
141{
142
143namespace lbt = libtorrent;
144namespace fs = boost::filesystem;
145
146using fs::path;
147using fs::ifstream;
148using fs::ofstream;
149using boost::serialization::make_nvp;
150
151lbt::entry haldecode(const wpath &file) 
152{
153        ifstream fs(file, ifstream::binary);
154        if (fs.is_open()) 
155        {
156                fs.unsetf(ifstream::skipws);
157                return lbt::bdecode(std::istream_iterator<char>(fs), std::istream_iterator<char>());
158        }
159        else return lbt::entry();
160}
161
162bool halencode(const wpath &file, const lbt::entry &e) 
163{
164        fs::ofstream fs(file, ofstream::binary);
165
166        if (!fs.is_open()) 
167                return false;
168       
169        lbt::bencode(std::ostream_iterator<char>(fs), e);
170        return true;
171}
172
173BitTorrent& bittorrent()
174{
175        static BitTorrent t;
176        return t;
177}
178
179bool operator!=(const lbt::dht_settings& lhs, const lbt::dht_settings& rhs)
180{
181        return lhs.max_peers_reply != rhs.max_peers_reply ||
182                   lhs.search_branching != rhs.search_branching ||
183                   lhs.service_port != rhs.service_port ||
184           lhs.max_fail_count != rhs.max_fail_count;
185}
186
187template<typename Addr>
188void write_range(fs::ofstream& ofs, const lbt::ip_range<Addr>& range)
189{ 
190        const typename Addr::bytes_type first = range.first.to_bytes();
191        const typename Addr::bytes_type last = range.last.to_bytes();
192        ofs.write((char*)first.elems, first.size());
193        ofs.write((char*)last.elems, last.size());
194}
195
196template<typename Addr>
197void write_vec_range(fs::ofstream& ofs, const std::vector<lbt::ip_range<Addr> >& vec)
198{ 
199        ofs << vec.size();
200       
201        for (typename std::vector<lbt::ip_range<Addr> >::const_iterator i=vec.begin(); 
202                i != vec.end(); ++i)
203        {
204                write_range(ofs, *i);
205        }
206}
207
208template<typename Addr>
209void read_range_to_filter(fs::ifstream& ifs, lbt::ip_filter& ip_filter)
210{ 
211        typename Addr::bytes_type first;
212        typename Addr::bytes_type last;
213        ifs.read((char*)first.elems, first.size());
214        ifs.read((char*)last.elems, last.size());       
215       
216        ip_filter.add_rule(Addr(first), Addr(last),
217                lbt::ip_filter::blocked);
218}
219
220static Event::eventLevel lbtAlertToHalEvent(lbt::alert::severity_t severity)
221{
222        switch (severity)
223        {
224        case lbt::alert::debug:
225                return Event::debug;
226               
227        case lbt::alert::info:
228        case lbt::alert::warning:
229                return Event::info;
230               
231        case lbt::alert::critical:
232        case lbt::alert::fatal:
233                return Event::critical;
234               
235        default:
236                return Event::none;
237        }
238}
239
240const PeerDetails& TorrentDetail::peerDetails() const
241{
242        if (!peerDetailsFilled_)
243        {
244                bittorrent().getAllPeerDetails(hal::to_utf8(filename_), peerDetails_);
245                peerDetailsFilled_ = true;
246        }
247       
248        return peerDetails_;
249}
250
251bool nameLess(const TorrentDetail_ptr& left, const TorrentDetail_ptr& right)
252{
253        return left->state() < right->state();
254}
255
256void TorrentDetails::sort(sortIndex i) const
257{
258        std::stable_sort(torrents_.begin(), torrents_.end(), &nameLess);
259}
260
261class BitTorrent_impl
262{
263        friend class BitTorrent;
264       
265public:
266       
267        ~BitTorrent_impl()
268        {
269                keepChecking_ = false;
270               
271                saveTorrentData();
272               
273                try
274                {
275               
276                if (ip_filter_changed_)
277                {       
278                        fs::ofstream ofs(workingDirectory/L"IPFilter.bin", std::ios::binary);
279//                      boost::archive::binary_oarchive oba(ofs);
280                       
281                        lbt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();   
282                       
283                        std::vector<lbt::ip_range<asio::ip::address_v4> > v4(vectors.get<0>());
284                        std::vector<lbt::ip_range<asio::ip::address_v6> > v6(vectors.get<1>());
285                       
286                        v4.erase(std::remove(v4.begin(), v4.end(), 0), v4.end());
287                        v6.erase(std::remove(v6.begin(), v6.end(), 0), v6.end());
288
289                        write_vec_range(ofs, v4);
290//                      write_vec_range(ofs, v6);
291                }       
292                }
293                catch(std::exception& e)
294                {
295                        hal::event().post(boost::shared_ptr<hal::EventDetail>(
296                                new hal::EventStdException(Event::critical, e, L"~BitTorrent_impl"))); 
297//                      ::MessageBox(0, (wformat(L"Save data exception: %1%") % e.what()).str().c_str(), L"Exception", 0);
298                }
299        }
300       
301        void pop_alerts()
302        {
303                if (keepChecking_)
304                {
305                        std::auto_ptr<lbt::alert> p_alert = theSession.pop_alert();
306                       
307                        while (p_alert.get())
308                        {       
309                                if (lbt::peer_error_alert* peer = dynamic_cast<lbt::peer_error_alert*>(p_alert.get()))
310                                {
311                                        event().post(shared_ptr<EventDetail>(
312                                                new EventPeerAlert(lbtAlertToHalEvent(p_alert->severity()), 
313                                                        p_alert->timestamp(), hal::str_to_wstr(p_alert->msg()))));                     
314                                }
315                                else
316                                {
317                                        event().post(shared_ptr<EventDetail>(
318                                                new EventLibtorrent(lbtAlertToHalEvent(p_alert->severity()), 
319                                                        p_alert->timestamp(), Event::unclassified, hal::str_to_wstr(p_alert->msg()))));
320                                }
321                               
322                                p_alert = theSession.pop_alert();
323                        }
324                       
325                        timer_.expires_from_now(boost::posix_time::seconds(5));
326                        timer_.async_wait(bind(&BitTorrent_impl::pop_alerts, this));
327                }
328        }
329       
330        void saveTorrentData()
331        {       try
332                {
333               
334                fs::wofstream ofs(workingDirectory/L"Torrents.xml");
335                boost::archive::xml_woarchive oxa(ofs);
336               
337                oxa << make_nvp("torrents", torrents);
338                       
339                if (dht_on_) 
340                {       
341                        halencode(workingDirectory/L"DHTState.bin", theSession.dht_state());
342                }
343               
344                }               
345                catch(std::exception& e)
346                {
347                        event().post(shared_ptr<EventDetail>(\
348                                new EventStdException(Event::critical, e, L"saveTorrentData")));
349                }
350        }
351       
352        int defTorrentMaxConn() { return defTorrentMaxConn_; }
353        int defTorrentMaxUpload() { return defTorrentMaxUpload_; }
354        float defTorrentDownload() { return defTorrentDownload_; }
355        float defTorrentUpload() { return defTorrentUpload_; }
356       
357private:
358        BitTorrent_impl() :
359                theSession(lbt::fingerprint("HL", 0, 2, 9, 0)),
360                timer_(io_),
361                keepChecking_(false),
362                workingDirectory(hal::app().exe_path().branch_path()),
363                defTorrentMaxConn_(-1),
364                defTorrentMaxUpload_(-1),
365                defTorrentDownload_(-1),
366                defTorrentUpload_(-1),
367                ip_filter_on_(false),
368                ip_filter_loaded_(false),
369                ip_filter_changed_(false),
370                ip_filter_count_(0),
371                dht_on_(false)
372        {
373                TorrentInternal::the_session_ = &theSession;
374               
375                theSession.set_severity_level(lbt::alert::debug);
376               
377                theSession.add_extension(&lbt::create_metadata_plugin);
378                theSession.add_extension(&lbt::create_ut_pex_plugin);
379                theSession.set_max_half_open_connections(10);
380
381                try
382                {       
383                        fs::wifstream ifs(workingDirectory/L"Torrents.xml");
384                        if (ifs)
385                        {
386                                boost::archive::xml_wiarchive ia(ifs);                 
387                                ia >> make_nvp("torrents", torrents);
388                        }
389                }
390                catch(const std::exception& e)
391                {
392                        event().post(shared_ptr<EventDetail>(\
393                                new EventStdException(Event::fatal, e, L"Loading Torrents.xml")));
394                }
395               
396                if (exists(workingDirectory/L"DHTState.bin"))
397                {
398                        try
399                        {
400                                dht_state_ = haldecode(workingDirectory/L"DHTState.bin");
401                        }               
402                        catch(const std::exception& e)
403                        {
404                                event().post(shared_ptr<EventDetail>(
405                                        new EventStdException(Event::critical, e, L"Loading DHTState.bin")));
406                        }
407                }
408               
409                {       lbt::session_settings settings = theSession.settings();
410                        settings.user_agent = "Halite v 0.2.9";
411                        theSession.set_settings(settings);
412                }
413               
414                timer_.expires_from_now(boost::posix_time::seconds(5));
415                timer_.async_wait(bind(&BitTorrent_impl::pop_alerts, this));
416        }
417       
418        lbt::entry prepTorrent(wpath filename, wpath saveDirectory);
419        void removalThread(lbt::torrent_handle handle, bool wipeFiles);
420       
421        lbt::session theSession;
422        asio::io_service io_;
423        asio::deadline_timer timer_;
424        bool keepChecking_;
425       
426        TorrentMap torrents;
427        const wpath workingDirectory;
428       
429        int defTorrentMaxConn_;
430        int defTorrentMaxUpload_;
431        float defTorrentDownload_;
432        float defTorrentUpload_;
433       
434        bool ip_filter_on_;
435        bool ip_filter_loaded_;
436        bool ip_filter_changed_;
437        lbt::ip_filter ip_filter_;
438        size_t ip_filter_count_;
439       
440        void ip_filter_count();
441        void ip_filter_load(progressCallback fn);
442        void ip_filter_import(std::vector<lbt::ip_range<asio::ip::address_v4> >& v4,
443                std::vector<lbt::ip_range<asio::ip::address_v6> >& v6);
444       
445        bool dht_on_;
446        lbt::dht_settings dht_settings_;
447        lbt::entry dht_state_;
448};
449
450BitTorrent::BitTorrent() :
451        pimpl(new BitTorrent_impl())
452{}
453
454#define HAL_GENERIC_TORRENT_EXCEPTION_CATCH(TORRENT, FUNCTION) \
455catch (const lbt::invalid_handle&)\
456{\
457        event().post(shared_ptr<EventDetail>(\
458                new EventInvalidTorrent(Event::critical, Event::invalidTorrent, TORRENT, FUNCTION)));\
459}\
460catch (const std::exception& e)\
461{\
462        event().post(shared_ptr<EventDetail>(\
463                new EventTorrentException(Event::critical, Event::torrentException, e.what(), TORRENT, FUNCTION)));\
464}
465
466void BitTorrent::shutDownSession()
467{
468        pimpl.reset();
469}
470
471void BitTorrent::saveTorrentData()
472{
473        pimpl->saveTorrentData();
474}
475
476bool BitTorrent::listenOn(pair<int, int> const& range)
477{
478        if (!pimpl->theSession.is_listening())
479        {
480                bool result = pimpl->theSession.listen_on(range);
481               
482                return result; 
483        }
484        else
485        {
486                int port = pimpl->theSession.listen_port();
487               
488                if (port < range.first || port > range.second)
489                        return pimpl->theSession.listen_on(range);     
490                else
491                        return true;
492        }
493}
494
495int BitTorrent::isListeningOn() 
496{
497        if (!pimpl->theSession.is_listening())
498                return -1;     
499        else
500                return pimpl->theSession.listen_port();
501}
502
503void BitTorrent::stopListening()
504{
505        ensure_dht_off();
506        pimpl->theSession.listen_on(make_pair(0, 0));
507}
508
509bool BitTorrent::ensure_dht_on()
510{
511        if (!pimpl->dht_on_)
512        {               
513                try
514                {
515                pimpl->theSession.start_dht(pimpl->dht_state_);
516                pimpl->dht_on_ = true;
517                }
518                catch(...)
519                {}
520        }
521                return pimpl->dht_on_;
522}
523
524void BitTorrent::ensure_dht_off()
525{
526        if (pimpl->dht_on_)
527        {
528                pimpl->theSession.stop_dht();           
529                pimpl->dht_on_ = false;
530        }
531}
532
533void BitTorrent::setDhtSettings(int max_peers_reply, int search_branching, 
534        int service_port, int max_fail_count)
535{
536        lbt::dht_settings settings;
537        settings.max_peers_reply = max_peers_reply;
538        settings.search_branching = search_branching;
539        settings.service_port = service_port;
540        settings.max_fail_count = max_fail_count;
541       
542        if (pimpl->dht_settings_ != settings)
543        {
544                pimpl->dht_settings_ = settings;
545                pimpl->theSession.set_dht_settings(pimpl->dht_settings_);
546        }
547}
548
549void BitTorrent::setSessionLimits(int maxConn, int maxUpload)
550{               
551        pimpl->theSession.set_max_uploads(maxUpload);
552        pimpl->theSession.set_max_connections(maxConn);
553}
554
555void BitTorrent::setSessionSpeed(float download, float upload)
556{
557        int down = (download > 0) ? static_cast<int>(download*1024) : -1;
558        pimpl->theSession.set_download_rate_limit(down);
559        int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
560        pimpl->theSession.set_upload_rate_limit(up);
561}
562
563void BitTorrent_impl::ip_filter_count()
564{
565        lbt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();
566       
567        vectors.get<0>().erase(std::remove(vectors.get<0>().begin(), vectors.get<0>().end(), 0),
568                vectors.get<0>().end());
569        vectors.get<1>().erase(std::remove(vectors.get<1>().begin(), vectors.get<1>().end(), 0),
570                vectors.get<1>().end());
571        ip_filter_count_ = vectors.get<0>().size() + vectors.get<1>().size();
572}
573
574void BitTorrent_impl::ip_filter_load(progressCallback fn)
575{
576        fs::ifstream ifs(workingDirectory/L"IPFilter.bin", std::ios::binary);
577        if (ifs)
578        {
579                size_t v4_size;
580                ifs >> v4_size;
581               
582                size_t total = v4_size/100;
583                size_t previous = 0;
584                                       
585                for(unsigned i=0; i<v4_size; ++i)
586                {
587                        if (i-previous > total)
588                        {
589                                previous = i;
590                                if (fn) if (fn(size_t(i/total))) break;
591                        }
592                       
593                        read_range_to_filter<asio::ip::address_v4>(ifs, ip_filter_);
594                }
595        }       
596}
597
598void  BitTorrent_impl::ip_filter_import(std::vector<lbt::ip_range<asio::ip::address_v4> >& v4,
599        std::vector<lbt::ip_range<asio::ip::address_v6> >& v6)
600{
601        for(std::vector<lbt::ip_range<asio::ip::address_v4> >::iterator i=v4.begin();
602                i != v4.end(); ++i)
603        {
604                ip_filter_.add_rule(i->first, i->last, lbt::ip_filter::blocked);
605        }
606/*      for(std::vector<lbt::ip_range<asio::ip::address_v6> >::iterator i=v6.begin();
607                i != v6.end(); ++i)
608        {
609                ip_filter_.add_rule(i->first, i->last, lbt::ip_filter::blocked);
610        }
611*/     
612        /* Note here we do not set ip_filter_changed_ */
613}
614
615void BitTorrent::ensure_ip_filter_on(progressCallback fn)
616{
617        if (!pimpl->ip_filter_loaded_)
618        {
619                pimpl->ip_filter_load(fn);
620                pimpl->ip_filter_loaded_ = true;
621        }
622       
623        if (!pimpl->ip_filter_on_)
624        {
625                pimpl->theSession.set_ip_filter(pimpl->ip_filter_);
626                pimpl->ip_filter_on_ = true;
627                pimpl->ip_filter_count();
628        }
629}
630
631void BitTorrent::ensure_ip_filter_off()
632{
633        pimpl->theSession.set_ip_filter(lbt::ip_filter());
634        pimpl->ip_filter_on_ = false;
635}
636
637#ifndef TORRENT_DISABLE_ENCRYPTION     
638void BitTorrent::ensure_pe_on(int enc_level, int in_enc_policy, int out_enc_policy, bool prefer_rc4)
639{
640        lbt::pe_settings pe;
641       
642        switch (enc_level)
643        {
644                case 0:
645                        pe.allowed_enc_level = lbt::pe_settings::plaintext;
646                        break;
647                case 1:
648                        pe.allowed_enc_level = lbt::pe_settings::rc4;
649                        break;
650                case 2:
651                        pe.allowed_enc_level = lbt::pe_settings::both;
652                        break;
653                default:
654                        pe.allowed_enc_level = lbt::pe_settings::both;
655                       
656                        hal::event().post(shared_ptr<hal::EventDetail>(
657                                new hal::EventGeneral(hal::Event::warning, hal::Event::unclassified, 
658                                        (wformat(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % enc_level).str())));
659        }
660
661        switch (in_enc_policy)
662        {
663                case 0:
664                        pe.in_enc_policy = lbt::pe_settings::forced;
665                        break;
666                case 1:
667                        pe.in_enc_policy = lbt::pe_settings::enabled;
668                        break;
669                case 2:
670                        pe.in_enc_policy = lbt::pe_settings::disabled;
671                        break;
672                default:
673                        pe.in_enc_policy = lbt::pe_settings::enabled;
674                       
675                        hal::event().post(shared_ptr<hal::EventDetail>(
676                                new hal::EventGeneral(hal::Event::warning, hal::Event::unclassified, 
677                                        (wformat(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
678        }
679
680        switch (out_enc_policy)
681        {
682                case 0:
683                        pe.out_enc_policy = lbt::pe_settings::forced;
684                        break;
685                case 1:
686                        pe.out_enc_policy = lbt::pe_settings::enabled;
687                        break;
688                case 2:
689                        pe.out_enc_policy = lbt::pe_settings::disabled;
690                        break;
691                default:
692                        pe.out_enc_policy = lbt::pe_settings::enabled;
693                       
694                        hal::event().post(shared_ptr<hal::EventDetail>(
695                                new hal::EventGeneral(hal::Event::warning, hal::Event::unclassified, 
696                                        (wformat(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
697        }
698       
699        pe.prefer_rc4 = prefer_rc4;
700       
701        pimpl->theSession.set_pe_settings(pe);
702}
703
704void BitTorrent::ensure_pe_off()
705{
706        lbt::pe_settings pe;
707        pe.out_enc_policy = lbt::pe_settings::disabled;
708        pe.in_enc_policy = lbt::pe_settings::disabled;
709       
710        pe.allowed_enc_level = lbt::pe_settings::both;
711        pe.prefer_rc4 = true;
712       
713        pimpl->theSession.set_pe_settings(pe);
714}
715#endif
716
717void BitTorrent::ip_v4_filter_block(asio::ip::address_v4 first, asio::ip::address_v4 last)
718{
719        pimpl->ip_filter_.add_rule(first, last, lbt::ip_filter::blocked);
720        pimpl->ip_filter_count();
721        pimpl->ip_filter_changed_ = true;
722}
723
724void BitTorrent::ip_v6_filter_block(asio::ip::address_v6 first, asio::ip::address_v6 last)
725{
726        pimpl->ip_filter_.add_rule(first, last, lbt::ip_filter::blocked);
727        pimpl->ip_filter_count();
728        pimpl->ip_filter_changed_ = true;
729}
730
731size_t BitTorrent::ip_filter_size()
732{
733        return pimpl->ip_filter_count_;
734}
735
736void BitTorrent::clearIpFilter()
737{
738        pimpl->ip_filter_ = lbt::ip_filter();
739        pimpl->theSession.set_ip_filter(lbt::ip_filter());     
740        pimpl->ip_filter_changed_ = true;
741        pimpl->ip_filter_count();
742}
743
744void BitTorrent::ip_filter_import_dat(boost::filesystem::path file, progressCallback fn, bool octalFix)
745{
746        try
747        {
748
749        fs::ifstream ifs(file); 
750        if (ifs)
751        {
752                boost::uintmax_t total = fs::file_size(file)/100;
753                boost::uintmax_t progress = 0;
754                boost::uintmax_t previous = 0;
755               
756                boost::regex reg("\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*-\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*.*");
757                boost::regex ip_reg("0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)");
758                boost::smatch m;
759               
760                string ip_address_line;         
761                while (!std::getline(ifs, ip_address_line).eof())
762                {               
763                        progress += (ip_address_line.length() + 2);
764                        if (progress-previous > total)
765                        {
766                                previous = progress;
767                                if (fn)
768                                {
769                                        if (fn(size_t(progress/total))) 
770                                                break;
771                                }
772                        }
773                       
774                        if (boost::regex_match(ip_address_line, m, reg))
775                        {
776                                string first = m[1];
777                                string last = m[2];
778                               
779                                if (octalFix)
780                                {
781                                        if (boost::regex_match(first, m, ip_reg))
782                                        {
783                                                first = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
784                                                                ((m.length(2) != 0) ? m[2] : string("0")) + "." +
785                                                                ((m.length(3) != 0) ? m[3] : string("0")) + "." +
786                                                                ((m.length(4) != 0) ? m[4] : string("0"));
787                                        }                                       
788                                        if (boost::regex_match(last, m, ip_reg))
789                                        {
790                                                last = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
791                                                           ((m.length(2) != 0) ? m[2] : string("0")) + "." +
792                                                           ((m.length(3) != 0) ? m[3] : string("0")) + "." +
793                                                           ((m.length(4) != 0) ? m[4] : string("0"));
794                                        }
795                                }
796                               
797                                try
798                                {                       
799                                pimpl->ip_filter_.add_rule(asio::ip::address_v4::from_string(first),
800                                        asio::ip::address_v4::from_string(last), lbt::ip_filter::blocked);     
801                                }
802                                catch(...)
803                                {
804                                        hal::event().post(shared_ptr<hal::EventDetail>(new hal::EventDebug(hal::Event::info, from_utf8((format("Invalid IP range: %1%-%2%.") % first % last).str()))));
805                                }
806                        }
807                }
808        }
809       
810        pimpl->ip_filter_changed_ = true;
811        pimpl->ip_filter_count();
812       
813        }
814        catch(const std::exception& e)
815        {
816                event().post(shared_ptr<EventDetail>(
817                        new EventStdException(Event::critical, e, L"ip_filter_import_dat")));
818        }
819}
820
821const SessionDetail BitTorrent::getSessionDetails()
822{
823        SessionDetail details;
824       
825        details.port = pimpl->theSession.is_listening() ? pimpl->theSession.listen_port() : -1;
826       
827        lbt::session_status status = pimpl->theSession.status();
828       
829        details.speed = pair<double, double>(status.download_rate, status.upload_rate);
830       
831        details.dht_on = pimpl->dht_on_;
832        details.dht_nodes = status.dht_nodes;
833        details.dht_torrents = status.dht_torrents;
834       
835        details.ip_filter_on = pimpl->ip_filter_on_;
836        details.ip_ranges_filtered = pimpl->ip_filter_count_;
837       
838        return details;
839}
840
841
842void BitTorrent::setSessionHalfOpenLimit(int halfConn)
843{
844        pimpl->theSession.set_max_half_open_connections(halfConn);
845}
846
847void BitTorrent::setTorrentDefaults(int maxConn, int maxUpload, float download, float upload)
848{
849        pimpl->defTorrentMaxConn_ = maxConn;
850        pimpl->defTorrentMaxUpload_ = maxUpload;
851        pimpl->defTorrentDownload_ = download;
852        pimpl->defTorrentUpload_ = upload;
853}
854
855lbt::entry BitTorrent_impl::prepTorrent(wpath filename, wpath saveDirectory)
856{
857        lbt::entry resumeData; 
858        const wpath resumeFile = workingDirectory/L"resume"/filename.leaf();
859       
860        if (exists(resumeFile)) 
861        {
862                try 
863                {
864                        resumeData = haldecode(resumeFile);
865                }
866                catch(std::exception &e) 
867                {               
868                        hal::event().post(boost::shared_ptr<hal::EventDetail>(
869                                new hal::EventStdException(Event::critical, e, L"prepTorrent, Resume"))); 
870       
871//                      ::MessageBoxW(0, hal::str_to_wstr(ex.what()).c_str(), L"Resume Exception", MB_ICONERROR|MB_OK);
872                        remove(resumeFile);
873                }
874        }
875
876        if (!exists(workingDirectory/L"torrents"))
877                create_directory(workingDirectory/L"torrents");
878
879        if (!exists(workingDirectory/L"torrents"/filename.leaf()))
880                copy_file(filename.string(), workingDirectory/L"torrents"/filename.leaf());
881
882        if (!exists(saveDirectory))
883                create_directory(saveDirectory);
884       
885        return resumeData;
886}
887
888void BitTorrent::addTorrent(wpath file, wpath saveDirectory) 
889{
890        try 
891        {       
892        lbt::entry metadata = haldecode(file);
893        lbt::entry resumedata = pimpl->prepTorrent(file, saveDirectory);
894       
895        TorrentMap::const_iterator existing = pimpl->torrents.find(to_utf8(file.leaf()));
896       
897        if (existing == pimpl->torrents.end())
898        {               
899                lbt::torrent_handle handle = pimpl->theSession.add_torrent(metadata,
900                        to_utf8(saveDirectory.string()), resumedata);
901               
902                pimpl->torrents.insert(TorrentMap::value_type(to_utf8(file.leaf()), 
903                        TorrentInternal(handle, file.leaf(), saveDirectory)));
904        }
905
906        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(to_utf8(file.string()), "addTorrent")
907}
908
909void add_files(lbt::torrent_info& t, fs::path const& p, fs::path const& l)
910{
911        fs::path f(p / l);
912        if (fs::is_directory(f))
913        {
914                for (fs::directory_iterator i(f), end; i != end; ++i)
915                        add_files(t, p, l / i->leaf());
916        }
917        else
918        {
919        //      std::cerr << "adding \"" << l.string() << "\"\n";
920                lbt::file fi(f, lbt::file::in);
921                fi.seek(0, lbt::file::end);
922                libtorrent::size_type size = fi.tell();
923                t.add_file(l, size);
924        }
925}
926
927void BitTorrent::newTorrent(fs::wpath filename, fs::wpath files)
928{
929/*      try
930        {
931       
932        libtorrent::torrent_info t;
933        path full_path = pimpl->workingDirectory/"incoming"/files.leaf();
934       
935        ofstream out(filename, std::ios_base::binary);
936       
937        int piece_size = 256 * 1024;
938        char const* creator_str = "Halite v0.3 (libtorrent v0.11)";
939
940        add_files(t, full_path.branch_path(), full_path.leaf());
941        t.set_piece_size(piece_size);
942
943        lbt::storage st(t, full_path.branch_path());
944        t.add_tracker("http://www.nitcom.com.au/announce.php");
945        t.set_priv(false);
946        t.add_node(make_pair("192.168.11.12", 6881));
947
948        // calculate the hash for all pieces
949        int num = t.num_pieces();
950        std::vector<char> buf(piece_size);
951        for (int i = 0; i < num; ++i)
952        {
953                        st.read(&buf[0], i, 0, t.piece_size(i));
954                        libtorrent::hasher h(&buf[0], t.piece_size(i));
955                        t.set_hash(i, h.final());
956                //      std::cerr << (i+1) << "/" << num << "\r";
957        }
958
959        t.set_creator(creator_str);
960
961        // create the torrent and print it to out
962        lbt::entry e = t.create_torrent();
963        lbt::bencode(std::ostream_iterator<char>(out), e);
964        }
965        catch (std::exception& e)
966        {
967                ::MessageBoxA(0, e.what(), "Create Torrent exception.", 0);
968        }
969*/
970}
971
972void BitTorrent::getAllTorrentDetail_vec(TorrentDetail_vec& torrentsContainer)
973{
974        try {
975       
976        torrentsContainer.reserve(pimpl->torrents.size());
977       
978        foreach (TorrentPair t, pimpl->torrents)
979        {
980                torrentsContainer.push_back(t.second.getTorrentDetail_ptr());
981        }
982       
983        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "getAllTorrentDetail_vec")
984}
985
986TorrentDetail_ptr BitTorrent::getTorrentDetail_vec(string filename)
987{
988        try {
989       
990        TorrentMap::const_iterator i = pimpl->torrents.find(filename);
991       
992        if (i != pimpl->torrents.end())
993        {
994                return i->second.getTorrentDetail_ptr();
995        }
996       
997        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentDetail_ptr")
998       
999        return TorrentDetail_ptr();
1000}
1001
1002
1003TorrentDetails BitTorrent::getTorrentDetails(std::string selected, std::set<std::string> allSelected)
1004{
1005        TorrentDetails torrentDetails;
1006       
1007        torrentDetails.torrents_.reserve(pimpl->torrents.size());
1008       
1009        foreach (TorrentPair t, pimpl->torrents)
1010        {
1011                if (allSelected.find(hal::to_utf8(t.second.filename())) != allSelected.end())
1012                {
1013                        torrentDetails.selectedTorrents_.push_back(t.second.getTorrentDetail_ptr());
1014                }
1015               
1016                if (selected == hal::to_utf8(t.second.filename()))
1017                        torrentDetails.selectedTorrent_ = t.second.getTorrentDetail_ptr();
1018               
1019                torrentDetails.torrents_.push_back(t.second.getTorrentDetail_ptr());
1020        }
1021       
1022        return torrentDetails;
1023}
1024
1025void BitTorrent::resumeAll()
1026{
1027        try {
1028       
1029        for (TorrentMap::iterator iter = pimpl->torrents.begin(); 
1030                iter != pimpl->torrents.end(); /*Nothing here*/)
1031        {
1032                wpath file = pimpl->workingDirectory/L"torrents"/from_utf8((*iter).first);
1033               
1034                if (exists(file))
1035                {               
1036                        try 
1037                        {                               
1038                        lbt::entry metadata = haldecode(file);
1039                        lbt::entry resumedata = pimpl->prepTorrent(file, (*iter).second.saveDirectory());
1040                       
1041                        (*iter).second.setEntryData(metadata, resumedata);
1042                       
1043                        if ((*iter).second.state() == TorrentDetail::torrent_paused)
1044                                (*iter).second.pause();
1045                        else if ((*iter).second.state() == TorrentDetail::torrent_stopped)
1046                                (*iter).second.stop(); 
1047                        else
1048                                (*iter).second.resume();
1049                       
1050                        ++iter;
1051                        }
1052                        catch(const lbt::duplicate_torrent&)
1053                        {
1054                                hal::event().post(shared_ptr<hal::EventDetail>(new hal::EventDebug(hal::Event::debug, L"Encountered duplicate torrent")));
1055                               
1056                                ++iter; // Harmless, don't worry about it.
1057                        }
1058                        catch(const std::exception& e) 
1059                        {
1060                                hal::event().post(shared_ptr<hal::EventDetail>(new hal::EventStdException(hal::Event::warning, e, L"resumeAll")));
1061                               
1062                                pimpl->torrents.erase(iter++);
1063                        }                       
1064                }
1065                else
1066                {
1067                        pimpl->torrents.erase(iter++);
1068                }
1069        }
1070       
1071        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "resumeAll")
1072}
1073
1074void BitTorrent::closeAll()
1075{
1076        try {
1077       
1078        wpath resumeDir=pimpl->workingDirectory/L"resume";
1079       
1080        if (!pimpl->torrents.empty() && !exists(resumeDir))
1081                create_directory(resumeDir);
1082       
1083        foreach (TorrentPair t, pimpl->torrents)
1084        {
1085                t.second.handle().pause(); // NB. internal pause, not registered in Torrents.xml
1086                lbt::entry resumedata = t.second.handle().write_resume_data();
1087                pimpl->theSession.remove_torrent(t.second.handle());
1088               
1089                bool halencode_result = halencode(resumeDir/from_utf8(t.first), resumedata);
1090                assert(halencode_result);
1091        }
1092       
1093        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll")
1094}
1095
1096PeerDetail::PeerDetail(lbt::peer_info& peerInfo) :
1097        ipAddress(hal::str_to_wstr(peerInfo.ip.address().to_string())),
1098        speed(make_pair(peerInfo.payload_down_speed, peerInfo.payload_up_speed)),
1099        seed(peerInfo.seed),
1100        client(hal::str_to_wstr(peerInfo.client))
1101{
1102        std::vector<wstring> status_vec;
1103       
1104#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
1105        if (peerInfo.country[0] != 0 && peerInfo.country[1] != 0)
1106                ipAddress = (wformat(L"%1% (%2%)") % ipAddress % hal::str_to_wstr(string(peerInfo.country, 2))).str().c_str();
1107#endif 
1108
1109#ifndef TORRENT_DISABLE_ENCRYPTION             
1110        if (peerInfo.flags & lbt::peer_info::rc4_encrypted)
1111                status_vec.push_back(app().res_wstr(HAL_PEER_RC4_ENCRYPTED));           
1112        if (peerInfo.flags & lbt::peer_info::plaintext_encrypted)
1113                status_vec.push_back(app().res_wstr(HAL_PEER_PLAINTEXT_ENCRYPTED));
1114#endif
1115       
1116        if (peerInfo.flags & lbt::peer_info::interesting)
1117                status_vec.push_back(app().res_wstr(HAL_PEER_INTERESTING));     
1118        if (peerInfo.flags & lbt::peer_info::choked)
1119                status_vec.push_back(app().res_wstr(HAL_PEER_CHOKED)); 
1120        if (peerInfo.flags & lbt::peer_info::remote_interested)
1121                status_vec.push_back(app().res_wstr(HAL_PEER_REMOTE_INTERESTING));     
1122        if (peerInfo.flags & lbt::peer_info::remote_choked)
1123                status_vec.push_back(app().res_wstr(HAL_PEER_REMOTE_CHOKED));   
1124        if (peerInfo.flags & lbt::peer_info::supports_extensions)
1125                status_vec.push_back(app().res_wstr(HAL_PEER_SUPPORT_EXTENSIONS));     
1126        if (peerInfo.flags & lbt::peer_info::local_connection)
1127                status_vec.push_back(app().res_wstr(HAL_PEER_LOCAL_CONNECTION));               
1128        if (peerInfo.flags & lbt::peer_info::handshake)
1129                status_vec.push_back(app().res_wstr(HAL_PEER_HANDSHAKE));               
1130        if (peerInfo.flags & lbt::peer_info::connecting)
1131                status_vec.push_back(app().res_wstr(HAL_PEER_CONNECTING));             
1132        if (peerInfo.flags & lbt::peer_info::queued)
1133                status_vec.push_back(app().res_wstr(HAL_PEER_QUEUED));
1134               
1135        seed = (peerInfo.flags & lbt::peer_info::seed) ? true : false;
1136       
1137        if (!status_vec.empty()) status = status_vec[0];
1138       
1139        if (status_vec.size() > 1)
1140        {
1141                for (size_t i=1; i<status_vec.size(); ++i)
1142                {
1143                        status += L"; ";
1144                        status += status_vec[i];
1145                }
1146        }       
1147}
1148
1149void BitTorrent::getAllPeerDetails(string filename, PeerDetails& peerContainer)
1150{
1151        try {
1152       
1153        TorrentMap::iterator i = pimpl->torrents.find(filename);
1154       
1155        if (i != pimpl->torrents.end())
1156        {
1157                std::vector<lbt::peer_info> peerInfo;
1158                (*i).second.handle().get_peer_info(peerInfo);
1159               
1160                for (std::vector<lbt::peer_info>::iterator j = peerInfo.begin(); 
1161                        j != peerInfo.end(); ++j)
1162                {
1163                        peerContainer.push_back(PeerDetail(*j));
1164                }               
1165        }
1166       
1167        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getAllPeerDetails")
1168}
1169
1170bool BitTorrent::isTorrent(string filename)
1171{       
1172        try {
1173       
1174        return (pimpl->torrents.find(filename) != pimpl->torrents.end());
1175       
1176        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "isTorrent")
1177       
1178        return false;
1179}
1180
1181void BitTorrent::pauseTorrent(string filename)
1182{
1183        try {
1184       
1185        TorrentMap::iterator i = pimpl->torrents.find(filename);
1186       
1187        if (i != pimpl->torrents.end())
1188        {
1189                (*i).second.pause();
1190        }
1191       
1192        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "pauseTorrent")
1193}
1194
1195void BitTorrent::resumeTorrent(string filename)
1196{
1197        try {
1198       
1199        TorrentMap::iterator i = pimpl->torrents.find(filename);
1200       
1201        if (i != pimpl->torrents.end())
1202        {
1203                (*i).second.resume();
1204        }
1205       
1206        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "resumeTorrent")
1207}
1208
1209void BitTorrent::stopTorrent(string filename)
1210{
1211        try {
1212       
1213        TorrentMap::iterator i = pimpl->torrents.find(filename);
1214       
1215        if (i != pimpl->torrents.end())
1216        {
1217                (*i).second.stop();
1218        }
1219       
1220        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "stopTorrent")
1221}
1222
1223bool BitTorrent::isTorrentActive(string filename)
1224{
1225        try {
1226       
1227        TorrentMap::const_iterator i = pimpl->torrents.find(filename);
1228       
1229        if (i != pimpl->torrents.end())
1230        {
1231                return (*i).second.isActive();
1232        }
1233       
1234        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "isTorrentActive")
1235       
1236        return false; // ??? is this correct
1237}
1238
1239void BitTorrent::setTorrentLogin(std::string filename, std::wstring username, std::wstring password)
1240{
1241        try {
1242       
1243        TorrentMap::iterator i = pimpl->torrents.find(filename);
1244       
1245        if (i != pimpl->torrents.end())
1246        {
1247                (*i).second.setTrackerLogin(username, password);
1248        }
1249       
1250        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentLogin")
1251}
1252
1253std::pair<std::wstring, std::wstring>  BitTorrent::getTorrentLogin(std::string filename)
1254{
1255        try {
1256       
1257        TorrentMap::iterator i = pimpl->torrents.find(filename);
1258       
1259        if (i != pimpl->torrents.end())
1260        {
1261                return (*i).second.getTrackerLogin();
1262        }
1263       
1264        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentLogin")
1265       
1266        return std::make_pair(L"", L"");
1267}
1268
1269void BitTorrent_impl::removalThread(lbt::torrent_handle handle, bool wipeFiles)
1270{
1271        try {
1272       
1273        if (!wipeFiles)
1274                theSession.remove_torrent(handle);
1275        else
1276        {
1277                fs::path saveDirectory = handle.save_path();
1278                lbt::torrent_info info = handle.get_torrent_info();
1279               
1280                theSession.remove_torrent(handle);
1281               
1282                foreach (const lbt::file_entry& entry, make_pair(info.begin_files(), info.end_files()))
1283                {
1284                        path file_path = saveDirectory / entry.path;
1285                       
1286                        if (exists(file_path) && !file_path.empty())
1287                                remove_all(file_path);
1288                }
1289               
1290                if (info.num_files() != 1)
1291                {
1292                        path dir_path = saveDirectory / info.name();
1293                        if (exists(dir_path) && is_empty(dir_path))
1294                                remove_all(dir_path);
1295                }
1296        }       
1297       
1298        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "removalThread")
1299}
1300
1301void BitTorrent::removeTorrent(string filename)
1302{
1303        try {
1304       
1305        TorrentMap::iterator i = pimpl->torrents.find(filename);
1306       
1307        if (i != pimpl->torrents.end())
1308        {
1309                lbt::torrent_handle handle = (*i).second.handle();
1310                pimpl->torrents.erase(i);
1311                thread t(bind(&BitTorrent_impl::removalThread, &*pimpl, handle, false));
1312        }
1313       
1314        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "removeTorrent")
1315}
1316
1317void BitTorrent::removeTorrentWipeFiles(string filename)
1318{
1319        try {
1320       
1321        TorrentMap::iterator i = pimpl->torrents.find(filename);
1322       
1323        if (i != pimpl->torrents.end())
1324        {
1325                lbt::torrent_handle handle = (*i).second.handle();
1326                pimpl->torrents.erase(i);
1327                thread t(bind(&BitTorrent_impl::removalThread, &*pimpl, handle, true));
1328        }
1329       
1330        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "removeTorrentWipeFiles")
1331}
1332
1333void BitTorrent::reannounceTorrent(string filename)
1334{
1335        try {
1336       
1337        TorrentMap::iterator i = pimpl->torrents.find(filename);
1338       
1339        if (i != pimpl->torrents.end())
1340        {
1341                (*i).second.handle().force_reannounce();
1342        }
1343       
1344        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "reannounceTorrent")
1345
1346//      pimpl->theSession.add_dht_node(make_pair(string("192.168.11.4"),6881));
1347//      Temporary Hijack
1348
1349/*      ofstream out("dump.txt");
1350       
1351        lbt::entry ent = pimpl->theSession.dht_state();
1352        lbt::entry::dictionary_type dic = ent.dict();
1353       
1354        for (lbt::entry::dictionary_type::iterator j = dic.begin();
1355                j != dic.end(); ++j)
1356        {
1357                out << (*j).first << " " << (*j).second << std::endl;
1358        }               
1359*/     
1360}
1361
1362void BitTorrent::pauseAllTorrents()
1363{       
1364        try {
1365       
1366        for (TorrentMap::iterator iter = pimpl->torrents.begin(); 
1367                iter != pimpl->torrents.end(); ++iter)
1368        {
1369                (*iter).second.pause();
1370        }
1371       
1372        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "pauseAllTorrents")
1373}
1374
1375void BitTorrent::unpauseAllTorrents()
1376{       
1377        try {
1378       
1379        for (TorrentMap::iterator iter = pimpl->torrents.begin(); 
1380                iter != pimpl->torrents.end(); ++iter)
1381        {
1382                if (iter->second.state() == TorrentDetail::torrent_paused)
1383                        (*iter).second.resume();
1384        }
1385       
1386        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "unpauseAllTorrents")
1387}
1388
1389void BitTorrent::setTorrentLimit(string filename, int maxConn, int maxUpload)
1390{
1391        try {
1392       
1393        TorrentMap::iterator i = pimpl->torrents.find(filename);
1394       
1395        if (i != pimpl->torrents.end())
1396        {
1397                (*i).second.setConnectionLimit(maxConn, maxUpload);
1398        }
1399       
1400        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentLimit")
1401}
1402
1403void BitTorrent::setTorrentRatio(string filename, float ratio)
1404{
1405        try {
1406       
1407        TorrentMap::iterator i = pimpl->torrents.find(filename);
1408       
1409        if (i != pimpl->torrents.end())
1410        {
1411                (*i).second.setRatio(ratio);
1412        }
1413       
1414        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentRatio")
1415}
1416
1417float BitTorrent::getTorrentRatio(string filename)
1418{
1419        try {
1420       
1421        TorrentMap::iterator i = pimpl->torrents.find(filename);
1422       
1423        if (i != pimpl->torrents.end())
1424        {
1425                return (*i).second.getRatio();
1426        }
1427       
1428        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentRatio")
1429       
1430        return 0;
1431}
1432
1433void BitTorrent::setTorrentSpeed(string filename, float download, float upload)
1434{
1435        try {
1436       
1437        TorrentMap::iterator i = pimpl->torrents.find(filename);
1438       
1439        if (i != pimpl->torrents.end())
1440        {
1441                (*i).second.setTransferSpeed(download, upload);
1442        }
1443       
1444        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentSpeed")
1445}
1446
1447pair<int, int> BitTorrent::getTorrentLimit(string filename)
1448{
1449        try {
1450       
1451        TorrentMap::iterator i = pimpl->torrents.find(filename);
1452       
1453        if (i != pimpl->torrents.end())
1454        {
1455                return (*i).second.getConnectionLimit();
1456        }
1457       
1458        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentLimit")
1459       
1460        return pair<int, int>(0, 0);
1461}
1462
1463pair<float, float> BitTorrent::getTorrentSpeed(string filename)
1464{
1465        try {
1466       
1467        TorrentMap::iterator i = pimpl->torrents.find(filename);
1468       
1469        if (i != pimpl->torrents.end())
1470        {
1471                return (*i).second.getTransferSpeed();
1472        }
1473       
1474        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentSpeed")
1475       
1476        return pair<float, float>(0, 0);
1477}
1478
1479void BitTorrent::setTorrentTrackers(std::string filename, 
1480        const std::vector<TrackerDetail>& trackers)
1481{
1482        try {
1483       
1484        TorrentMap::iterator i = pimpl->torrents.find(filename);
1485       
1486        if (i != pimpl->torrents.end())
1487        {
1488                (*i).second.setTrackers(trackers);
1489        }
1490       
1491        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentTrackers")
1492}
1493
1494void BitTorrent::resetTorrentTrackers(std::string filename)
1495{
1496        try {
1497       
1498        TorrentMap::iterator i = pimpl->torrents.find(filename);
1499       
1500        if (i != pimpl->torrents.end())
1501        {
1502                (*i).second.resetTrackers();
1503        }
1504       
1505        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "resetTorrentTrackers")
1506}
1507
1508std::vector<TrackerDetail> BitTorrent::getTorrentTrackers(std::string filename)
1509{
1510        try {
1511       
1512        TorrentMap::iterator i = pimpl->torrents.find(filename);
1513       
1514        if (i != pimpl->torrents.end())
1515        {
1516                return (*i).second.getTrackers();
1517        }
1518       
1519        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentTrackers")
1520       
1521        return std::vector<TrackerDetail>();   
1522}
1523
1524void BitTorrent::startEventReceiver()
1525{
1526        pimpl->keepChecking_ = true;
1527        thread(bind(&asio::io_service::run, &pimpl->io_));
1528}
1529
1530void BitTorrent::stopEventReceiver()
1531{
1532        pimpl->keepChecking_ = false;
1533}
1534
1535int BitTorrent::defTorrentMaxConn() { return pimpl->defTorrentMaxConn_; }
1536int BitTorrent::defTorrentMaxUpload() { return pimpl->defTorrentMaxUpload_; }
1537float BitTorrent::defTorrentDownload() { return pimpl->defTorrentDownload_; }
1538float BitTorrent::defTorrentUpload() { return pimpl->defTorrentUpload_; }
1539       
1540};
Note: See TracBrowser for help on using the repository browser.