source: src/halTorrent.cpp @ 264

Revision 264, 40.3 KB checked in by Eoin, 12 years ago (diff)

Another overview layout in testing.

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(
257        boost::function<bool (const TorrentDetail_ptr&, const TorrentDetail_ptr&)> fn) const
258{
259        std::stable_sort(torrents_.begin(), torrents_.end(), fn);
260}
261
262class BitTorrent_impl
263{
264        friend class BitTorrent;
265       
266public:
267       
268        ~BitTorrent_impl()
269        {
270                keepChecking_ = false;
271               
272                saveTorrentData();
273               
274                try
275                {
276               
277                if (ip_filter_changed_)
278                {       
279                        fs::ofstream ofs(workingDirectory/L"IPFilter.bin", std::ios::binary);
280//                      boost::archive::binary_oarchive oba(ofs);
281                       
282                        lbt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();   
283                       
284                        std::vector<lbt::ip_range<asio::ip::address_v4> > v4(vectors.get<0>());
285                        std::vector<lbt::ip_range<asio::ip::address_v6> > v6(vectors.get<1>());
286                       
287                        v4.erase(std::remove(v4.begin(), v4.end(), 0), v4.end());
288                        v6.erase(std::remove(v6.begin(), v6.end(), 0), v6.end());
289
290                        write_vec_range(ofs, v4);
291//                      write_vec_range(ofs, v6);
292                }       
293                }
294                catch(std::exception& e)
295                {
296                        hal::event().post(boost::shared_ptr<hal::EventDetail>(
297                                new hal::EventStdException(Event::critical, e, L"~BitTorrent_impl"))); 
298//                      ::MessageBox(0, (wformat(L"Save data exception: %1%") % e.what()).str().c_str(), L"Exception", 0);
299                }
300        }
301       
302        void pop_alerts()
303        {
304                if (keepChecking_)
305                {
306                        std::auto_ptr<lbt::alert> p_alert = theSession.pop_alert();
307                       
308                        while (p_alert.get())
309                        {       
310                                if (lbt::peer_error_alert* peer = dynamic_cast<lbt::peer_error_alert*>(p_alert.get()))
311                                {
312                                        event().post(shared_ptr<EventDetail>(
313                                                new EventPeerAlert(lbtAlertToHalEvent(p_alert->severity()), 
314                                                        p_alert->timestamp(), hal::str_to_wstr(p_alert->msg()))));                     
315                                }
316                                else
317                                {
318                                        event().post(shared_ptr<EventDetail>(
319                                                new EventLibtorrent(lbtAlertToHalEvent(p_alert->severity()), 
320                                                        p_alert->timestamp(), Event::unclassified, hal::str_to_wstr(p_alert->msg()))));
321                                }
322                               
323                                p_alert = theSession.pop_alert();
324                        }
325                       
326                        timer_.expires_from_now(boost::posix_time::seconds(5));
327                        timer_.async_wait(bind(&BitTorrent_impl::pop_alerts, this));
328                }
329        }
330       
331        void saveTorrentData()
332        {       try
333                {
334               
335                fs::wofstream ofs(workingDirectory/L"Torrents.xml");
336                boost::archive::xml_woarchive oxa(ofs);
337               
338                oxa << make_nvp("torrents", torrents);
339                       
340                if (dht_on_) 
341                {       
342                        halencode(workingDirectory/L"DHTState.bin", theSession.dht_state());
343                }
344               
345                }               
346                catch(std::exception& e)
347                {
348                        event().post(shared_ptr<EventDetail>(\
349                                new EventStdException(Event::critical, e, L"saveTorrentData")));
350                }
351        }
352       
353        int defTorrentMaxConn() { return defTorrentMaxConn_; }
354        int defTorrentMaxUpload() { return defTorrentMaxUpload_; }
355        float defTorrentDownload() { return defTorrentDownload_; }
356        float defTorrentUpload() { return defTorrentUpload_; }
357       
358private:
359        BitTorrent_impl() :
360                theSession(lbt::fingerprint("HL", 0, 2, 9, 0)),
361                timer_(io_),
362                keepChecking_(false),
363                workingDirectory(hal::app().exe_path().branch_path()),
364                defTorrentMaxConn_(-1),
365                defTorrentMaxUpload_(-1),
366                defTorrentDownload_(-1),
367                defTorrentUpload_(-1),
368                ip_filter_on_(false),
369                ip_filter_loaded_(false),
370                ip_filter_changed_(false),
371                ip_filter_count_(0),
372                dht_on_(false)
373        {
374                TorrentInternal::the_session_ = &theSession;
375               
376                theSession.set_severity_level(lbt::alert::debug);
377               
378                theSession.add_extension(&lbt::create_metadata_plugin);
379                theSession.add_extension(&lbt::create_ut_pex_plugin);
380                theSession.set_max_half_open_connections(10);
381
382                try
383                {       
384                        fs::wifstream ifs(workingDirectory/L"Torrents.xml");
385                        if (ifs)
386                        {
387                                boost::archive::xml_wiarchive ia(ifs);                 
388                                ia >> make_nvp("torrents", torrents);
389                        }
390                }
391                catch(const std::exception& e)
392                {
393                        event().post(shared_ptr<EventDetail>(\
394                                new EventStdException(Event::fatal, e, L"Loading Torrents.xml")));
395                }
396               
397                if (exists(workingDirectory/L"DHTState.bin"))
398                {
399                        try
400                        {
401                                dht_state_ = haldecode(workingDirectory/L"DHTState.bin");
402                        }               
403                        catch(const std::exception& e)
404                        {
405                                event().post(shared_ptr<EventDetail>(
406                                        new EventStdException(Event::critical, e, L"Loading DHTState.bin")));
407                        }
408                }
409               
410                {       lbt::session_settings settings = theSession.settings();
411                        settings.user_agent = "Halite v 0.2.9";
412                        theSession.set_settings(settings);
413                }
414               
415                timer_.expires_from_now(boost::posix_time::seconds(5));
416                timer_.async_wait(bind(&BitTorrent_impl::pop_alerts, this));
417        }
418       
419        lbt::entry prepTorrent(wpath filename, wpath saveDirectory);
420        void removalThread(lbt::torrent_handle handle, bool wipeFiles);
421       
422        lbt::session theSession;
423        asio::io_service io_;
424        asio::deadline_timer timer_;
425        bool keepChecking_;
426       
427        TorrentMap torrents;
428        const wpath workingDirectory;
429       
430        int defTorrentMaxConn_;
431        int defTorrentMaxUpload_;
432        float defTorrentDownload_;
433        float defTorrentUpload_;
434       
435        bool ip_filter_on_;
436        bool ip_filter_loaded_;
437        bool ip_filter_changed_;
438        lbt::ip_filter ip_filter_;
439        size_t ip_filter_count_;
440       
441        void ip_filter_count();
442        void ip_filter_load(progressCallback fn);
443        void ip_filter_import(std::vector<lbt::ip_range<asio::ip::address_v4> >& v4,
444                std::vector<lbt::ip_range<asio::ip::address_v6> >& v6);
445       
446        bool dht_on_;
447        lbt::dht_settings dht_settings_;
448        lbt::entry dht_state_;
449};
450
451BitTorrent::BitTorrent() :
452        pimpl(new BitTorrent_impl())
453{}
454
455#define HAL_GENERIC_TORRENT_EXCEPTION_CATCH(TORRENT, FUNCTION) \
456catch (const lbt::invalid_handle&)\
457{\
458        event().post(shared_ptr<EventDetail>(\
459                new EventInvalidTorrent(Event::critical, Event::invalidTorrent, TORRENT, FUNCTION)));\
460}\
461catch (const std::exception& e)\
462{\
463        event().post(shared_ptr<EventDetail>(\
464                new EventTorrentException(Event::critical, Event::torrentException, e.what(), TORRENT, FUNCTION)));\
465}
466
467void BitTorrent::shutDownSession()
468{
469        pimpl.reset();
470}
471
472void BitTorrent::saveTorrentData()
473{
474        pimpl->saveTorrentData();
475}
476
477bool BitTorrent::listenOn(pair<int, int> const& range)
478{
479        if (!pimpl->theSession.is_listening())
480        {
481                bool result = pimpl->theSession.listen_on(range);
482               
483                return result; 
484        }
485        else
486        {
487                int port = pimpl->theSession.listen_port();
488               
489                if (port < range.first || port > range.second)
490                        return pimpl->theSession.listen_on(range);     
491                else
492                        return true;
493        }
494}
495
496int BitTorrent::isListeningOn() 
497{
498        if (!pimpl->theSession.is_listening())
499                return -1;     
500        else
501                return pimpl->theSession.listen_port();
502}
503
504void BitTorrent::stopListening()
505{
506        ensure_dht_off();
507        pimpl->theSession.listen_on(make_pair(0, 0));
508}
509
510bool BitTorrent::ensure_dht_on()
511{
512        if (!pimpl->dht_on_)
513        {               
514                try
515                {
516                pimpl->theSession.start_dht(pimpl->dht_state_);
517                pimpl->dht_on_ = true;
518                }
519                catch(...)
520                {}
521        }
522                return pimpl->dht_on_;
523}
524
525void BitTorrent::ensure_dht_off()
526{
527        if (pimpl->dht_on_)
528        {
529                pimpl->theSession.stop_dht();           
530                pimpl->dht_on_ = false;
531        }
532}
533
534void BitTorrent::setDhtSettings(int max_peers_reply, int search_branching, 
535        int service_port, int max_fail_count)
536{
537        lbt::dht_settings settings;
538        settings.max_peers_reply = max_peers_reply;
539        settings.search_branching = search_branching;
540        settings.service_port = service_port;
541        settings.max_fail_count = max_fail_count;
542       
543        if (pimpl->dht_settings_ != settings)
544        {
545                pimpl->dht_settings_ = settings;
546                pimpl->theSession.set_dht_settings(pimpl->dht_settings_);
547        }
548}
549
550void BitTorrent::setSessionLimits(int maxConn, int maxUpload)
551{               
552        pimpl->theSession.set_max_uploads(maxUpload);
553        pimpl->theSession.set_max_connections(maxConn);
554}
555
556void BitTorrent::setSessionSpeed(float download, float upload)
557{
558        int down = (download > 0) ? static_cast<int>(download*1024) : -1;
559        pimpl->theSession.set_download_rate_limit(down);
560        int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
561        pimpl->theSession.set_upload_rate_limit(up);
562}
563
564void BitTorrent_impl::ip_filter_count()
565{
566        lbt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();
567       
568        vectors.get<0>().erase(std::remove(vectors.get<0>().begin(), vectors.get<0>().end(), 0),
569                vectors.get<0>().end());
570        vectors.get<1>().erase(std::remove(vectors.get<1>().begin(), vectors.get<1>().end(), 0),
571                vectors.get<1>().end());
572        ip_filter_count_ = vectors.get<0>().size() + vectors.get<1>().size();
573}
574
575void BitTorrent_impl::ip_filter_load(progressCallback fn)
576{
577        fs::ifstream ifs(workingDirectory/L"IPFilter.bin", std::ios::binary);
578        if (ifs)
579        {
580                size_t v4_size;
581                ifs >> v4_size;
582               
583                size_t total = v4_size/100;
584                size_t previous = 0;
585                                       
586                for(unsigned i=0; i<v4_size; ++i)
587                {
588                        if (i-previous > total)
589                        {
590                                previous = i;
591                                if (fn) if (fn(size_t(i/total))) break;
592                        }
593                       
594                        read_range_to_filter<asio::ip::address_v4>(ifs, ip_filter_);
595                }
596        }       
597}
598
599void  BitTorrent_impl::ip_filter_import(std::vector<lbt::ip_range<asio::ip::address_v4> >& v4,
600        std::vector<lbt::ip_range<asio::ip::address_v6> >& v6)
601{
602        for(std::vector<lbt::ip_range<asio::ip::address_v4> >::iterator i=v4.begin();
603                i != v4.end(); ++i)
604        {
605                ip_filter_.add_rule(i->first, i->last, lbt::ip_filter::blocked);
606        }
607/*      for(std::vector<lbt::ip_range<asio::ip::address_v6> >::iterator i=v6.begin();
608                i != v6.end(); ++i)
609        {
610                ip_filter_.add_rule(i->first, i->last, lbt::ip_filter::blocked);
611        }
612*/     
613        /* Note here we do not set ip_filter_changed_ */
614}
615
616void BitTorrent::ensure_ip_filter_on(progressCallback fn)
617{
618        if (!pimpl->ip_filter_loaded_)
619        {
620                pimpl->ip_filter_load(fn);
621                pimpl->ip_filter_loaded_ = true;
622        }
623       
624        if (!pimpl->ip_filter_on_)
625        {
626                pimpl->theSession.set_ip_filter(pimpl->ip_filter_);
627                pimpl->ip_filter_on_ = true;
628                pimpl->ip_filter_count();
629        }
630}
631
632void BitTorrent::ensure_ip_filter_off()
633{
634        pimpl->theSession.set_ip_filter(lbt::ip_filter());
635        pimpl->ip_filter_on_ = false;
636}
637
638#ifndef TORRENT_DISABLE_ENCRYPTION     
639void BitTorrent::ensure_pe_on(int enc_level, int in_enc_policy, int out_enc_policy, bool prefer_rc4)
640{
641        lbt::pe_settings pe;
642       
643        switch (enc_level)
644        {
645                case 0:
646                        pe.allowed_enc_level = lbt::pe_settings::plaintext;
647                        break;
648                case 1:
649                        pe.allowed_enc_level = lbt::pe_settings::rc4;
650                        break;
651                case 2:
652                        pe.allowed_enc_level = lbt::pe_settings::both;
653                        break;
654                default:
655                        pe.allowed_enc_level = lbt::pe_settings::both;
656                       
657                        hal::event().post(shared_ptr<hal::EventDetail>(
658                                new hal::EventGeneral(hal::Event::warning, hal::Event::unclassified, 
659                                        (wformat(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % enc_level).str())));
660        }
661
662        switch (in_enc_policy)
663        {
664                case 0:
665                        pe.in_enc_policy = lbt::pe_settings::forced;
666                        break;
667                case 1:
668                        pe.in_enc_policy = lbt::pe_settings::enabled;
669                        break;
670                case 2:
671                        pe.in_enc_policy = lbt::pe_settings::disabled;
672                        break;
673                default:
674                        pe.in_enc_policy = lbt::pe_settings::enabled;
675                       
676                        hal::event().post(shared_ptr<hal::EventDetail>(
677                                new hal::EventGeneral(hal::Event::warning, hal::Event::unclassified, 
678                                        (wformat(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
679        }
680
681        switch (out_enc_policy)
682        {
683                case 0:
684                        pe.out_enc_policy = lbt::pe_settings::forced;
685                        break;
686                case 1:
687                        pe.out_enc_policy = lbt::pe_settings::enabled;
688                        break;
689                case 2:
690                        pe.out_enc_policy = lbt::pe_settings::disabled;
691                        break;
692                default:
693                        pe.out_enc_policy = lbt::pe_settings::enabled;
694                       
695                        hal::event().post(shared_ptr<hal::EventDetail>(
696                                new hal::EventGeneral(hal::Event::warning, hal::Event::unclassified, 
697                                        (wformat(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % in_enc_policy).str())));
698        }
699       
700        pe.prefer_rc4 = prefer_rc4;
701       
702        pimpl->theSession.set_pe_settings(pe);
703}
704
705void BitTorrent::ensure_pe_off()
706{
707        lbt::pe_settings pe;
708        pe.out_enc_policy = lbt::pe_settings::disabled;
709        pe.in_enc_policy = lbt::pe_settings::disabled;
710       
711        pe.allowed_enc_level = lbt::pe_settings::both;
712        pe.prefer_rc4 = true;
713       
714        pimpl->theSession.set_pe_settings(pe);
715}
716#endif
717
718void BitTorrent::ip_v4_filter_block(asio::ip::address_v4 first, asio::ip::address_v4 last)
719{
720        pimpl->ip_filter_.add_rule(first, last, lbt::ip_filter::blocked);
721        pimpl->ip_filter_count();
722        pimpl->ip_filter_changed_ = true;
723}
724
725void BitTorrent::ip_v6_filter_block(asio::ip::address_v6 first, asio::ip::address_v6 last)
726{
727        pimpl->ip_filter_.add_rule(first, last, lbt::ip_filter::blocked);
728        pimpl->ip_filter_count();
729        pimpl->ip_filter_changed_ = true;
730}
731
732size_t BitTorrent::ip_filter_size()
733{
734        return pimpl->ip_filter_count_;
735}
736
737void BitTorrent::clearIpFilter()
738{
739        pimpl->ip_filter_ = lbt::ip_filter();
740        pimpl->theSession.set_ip_filter(lbt::ip_filter());     
741        pimpl->ip_filter_changed_ = true;
742        pimpl->ip_filter_count();
743}
744
745void BitTorrent::ip_filter_import_dat(boost::filesystem::path file, progressCallback fn, bool octalFix)
746{
747        try
748        {
749
750        fs::ifstream ifs(file); 
751        if (ifs)
752        {
753                boost::uintmax_t total = fs::file_size(file)/100;
754                boost::uintmax_t progress = 0;
755                boost::uintmax_t previous = 0;
756               
757                boost::regex reg("\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*-\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*.*");
758                boost::regex ip_reg("0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)");
759                boost::smatch m;
760               
761                string ip_address_line;         
762                while (!std::getline(ifs, ip_address_line).eof())
763                {               
764                        progress += (ip_address_line.length() + 2);
765                        if (progress-previous > total)
766                        {
767                                previous = progress;
768                                if (fn)
769                                {
770                                        if (fn(size_t(progress/total))) 
771                                                break;
772                                }
773                        }
774                       
775                        if (boost::regex_match(ip_address_line, m, reg))
776                        {
777                                string first = m[1];
778                                string last = m[2];
779                               
780                                if (octalFix)
781                                {
782                                        if (boost::regex_match(first, m, ip_reg))
783                                        {
784                                                first = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
785                                                                ((m.length(2) != 0) ? m[2] : string("0")) + "." +
786                                                                ((m.length(3) != 0) ? m[3] : string("0")) + "." +
787                                                                ((m.length(4) != 0) ? m[4] : string("0"));
788                                        }                                       
789                                        if (boost::regex_match(last, m, ip_reg))
790                                        {
791                                                last = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
792                                                           ((m.length(2) != 0) ? m[2] : string("0")) + "." +
793                                                           ((m.length(3) != 0) ? m[3] : string("0")) + "." +
794                                                           ((m.length(4) != 0) ? m[4] : string("0"));
795                                        }
796                                }
797                               
798                                try
799                                {                       
800                                pimpl->ip_filter_.add_rule(asio::ip::address_v4::from_string(first),
801                                        asio::ip::address_v4::from_string(last), lbt::ip_filter::blocked);     
802                                }
803                                catch(...)
804                                {
805                                        hal::event().post(shared_ptr<hal::EventDetail>(new hal::EventDebug(hal::Event::info, from_utf8((format("Invalid IP range: %1%-%2%.") % first % last).str()))));
806                                }
807                        }
808                }
809        }
810       
811        pimpl->ip_filter_changed_ = true;
812        pimpl->ip_filter_count();
813       
814        }
815        catch(const std::exception& e)
816        {
817                event().post(shared_ptr<EventDetail>(
818                        new EventStdException(Event::critical, e, L"ip_filter_import_dat")));
819        }
820}
821
822const SessionDetail BitTorrent::getSessionDetails()
823{
824        SessionDetail details;
825       
826        details.port = pimpl->theSession.is_listening() ? pimpl->theSession.listen_port() : -1;
827       
828        lbt::session_status status = pimpl->theSession.status();
829       
830        details.speed = pair<double, double>(status.download_rate, status.upload_rate);
831       
832        details.dht_on = pimpl->dht_on_;
833        details.dht_nodes = status.dht_nodes;
834        details.dht_torrents = status.dht_torrents;
835       
836        details.ip_filter_on = pimpl->ip_filter_on_;
837        details.ip_ranges_filtered = pimpl->ip_filter_count_;
838       
839        return details;
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        for (TorrentMap::const_iterator i=pimpl->torrents.begin(), e=pimpl->torrents.end(); i != e; ++i)
979        {
980                torrentsContainer.push_back((*i).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/*const TorrentDetails& BitTorrent::getTorrentDetails(std::string selected, std::set<std::string> allSelected)
1003{
1004        return updateTorrentDetails(selected, allSelected);
1005}
1006*/
1007const TorrentDetails& BitTorrent::torrentDetails()
1008{
1009        return torrentDetails_;
1010}
1011
1012const TorrentDetails& BitTorrent::updateTorrentDetails(std::string focused, std::set<std::string> selected)
1013{
1014        try {
1015       
1016        mutex_t::scoped_lock l(torrentDetails_.mutex_); 
1017       
1018        torrentDetails_.clearAll(l);
1019       
1020        torrentDetails_.torrents_.reserve(pimpl->torrents.size());
1021       
1022        for (TorrentMap::const_iterator i=pimpl->torrents.begin(), e=pimpl->torrents.end(); i != e; ++i)
1023        {       
1024                string utf8Filename = hal::to_utf8((*i).second.filename());
1025                TorrentDetail_ptr pT = (*i).second.getTorrentDetail_ptr();
1026               
1027                if (selected.find(utf8Filename) != selected.end())
1028                {
1029                        torrentDetails_.selectedTorrents_.push_back(pT);
1030                }
1031               
1032                if (focused == utf8Filename)
1033                        torrentDetails_.selectedTorrent_ = pT;
1034               
1035                torrentDetails_.torrentMap_[(*i).second.filename()] = pT;
1036                torrentDetails_.torrents_.push_back(pT);
1037        }
1038       
1039        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "updateTorrentDetails")
1040       
1041        return torrentDetails_;
1042}
1043
1044void BitTorrent::resumeAll()
1045{
1046        try {
1047       
1048        for (TorrentMap::iterator iter = pimpl->torrents.begin(); 
1049                iter != pimpl->torrents.end(); /*Nothing here*/)
1050        {
1051                wpath file = pimpl->workingDirectory/L"torrents"/from_utf8((*iter).first);
1052               
1053                if (exists(file))
1054                {               
1055                        try 
1056                        {                               
1057                        lbt::entry metadata = haldecode(file);
1058                        lbt::entry resumedata = pimpl->prepTorrent(file, (*iter).second.saveDirectory());
1059                       
1060                        (*iter).second.setEntryData(metadata, resumedata);
1061                       
1062                        if ((*iter).second.state() == TorrentDetail::torrent_paused)
1063                                (*iter).second.pause();
1064                        else if ((*iter).second.state() == TorrentDetail::torrent_stopped)
1065                                (*iter).second.stop(); 
1066                        else
1067                                (*iter).second.resume();
1068                       
1069                        ++iter;
1070                        }
1071                        catch(const lbt::duplicate_torrent&)
1072                        {
1073                                hal::event().post(shared_ptr<hal::EventDetail>(new hal::EventDebug(hal::Event::debug, L"Encountered duplicate torrent")));
1074                               
1075                                ++iter; // Harmless, don't worry about it.
1076                        }
1077                        catch(const std::exception& e) 
1078                        {
1079                                hal::event().post(shared_ptr<hal::EventDetail>(new hal::EventStdException(hal::Event::warning, e, L"resumeAll")));
1080                               
1081                                pimpl->torrents.erase(iter++);
1082                        }                       
1083                }
1084                else
1085                {
1086                        pimpl->torrents.erase(iter++);
1087                }
1088        }
1089       
1090        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "resumeAll")
1091}
1092
1093void BitTorrent::closeAll()
1094{
1095        try {
1096       
1097        wpath resumeDir=pimpl->workingDirectory/L"resume";
1098       
1099        if (!pimpl->torrents.empty() && !exists(resumeDir))
1100                create_directory(resumeDir);
1101       
1102        for (TorrentMap::const_iterator i=pimpl->torrents.begin(), e=pimpl->torrents.end(); i != e; ++i)
1103        {
1104                if ((*i).second.inSession())
1105                {
1106                        (*i).second.handle().pause(); // NB. internal pause, not registered in Torrents.xml
1107                }
1108        }
1109       
1110        // Ok this polling loop here is a bit curde, but a blocking wait is actually appropiate.
1111        lbt::session_status status = pimpl->theSession.status();       
1112        while (status.download_rate > 0 || status.upload_rate > 0)
1113        {
1114                Sleep(200);
1115                status = pimpl->theSession.status();
1116        }
1117       
1118        for (TorrentMap::const_iterator i=pimpl->torrents.begin(), e=pimpl->torrents.end(); i != e; ++i)
1119        {
1120                if ((*i).second.inSession())
1121                {
1122                        lbt::entry resumedata = (*i).second.handle().write_resume_data();
1123                        pimpl->theSession.remove_torrent((*i).second.handle());
1124                       
1125                        bool halencode_result = halencode(resumeDir/from_utf8((*i).first), resumedata);
1126                        assert(halencode_result);
1127                }
1128        }
1129       
1130        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll")
1131}
1132
1133PeerDetail::PeerDetail(lbt::peer_info& peerInfo) :
1134        ipAddress(hal::safe_from_utf8(peerInfo.ip.address().to_string())),
1135        country(L""),
1136        speed(make_pair(peerInfo.payload_down_speed, peerInfo.payload_up_speed)),
1137        seed(peerInfo.seed),
1138        client(hal::safe_from_utf8(peerInfo.client))
1139{
1140        std::vector<wstring> status_vec;
1141       
1142#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
1143        if (peerInfo.country[0] != 0 && peerInfo.country[1] != 0)
1144                country = (wformat(L"(%1%)") % hal::safe_from_utf8(string(peerInfo.country, 2))).str().c_str();
1145#endif 
1146
1147        if (peerInfo.flags & lbt::peer_info::handshake)
1148        {
1149                status_vec.push_back(app().res_wstr(HAL_PEER_HANDSHAKE));
1150        }               
1151        else if (peerInfo.flags & lbt::peer_info::connecting)
1152        {
1153                status_vec.push_back(app().res_wstr(HAL_PEER_CONNECTING));
1154        }
1155        else
1156        {
1157        #ifndef TORRENT_DISABLE_ENCRYPTION             
1158                if (peerInfo.flags & lbt::peer_info::rc4_encrypted)
1159                        status_vec.push_back(app().res_wstr(HAL_PEER_RC4_ENCRYPTED));           
1160                if (peerInfo.flags & lbt::peer_info::plaintext_encrypted)
1161                        status_vec.push_back(app().res_wstr(HAL_PEER_PLAINTEXT_ENCRYPTED));
1162        #endif
1163               
1164                if (peerInfo.flags & lbt::peer_info::interesting)
1165                        status_vec.push_back(app().res_wstr(HAL_PEER_INTERESTING));     
1166                if (peerInfo.flags & lbt::peer_info::choked)
1167                        status_vec.push_back(app().res_wstr(HAL_PEER_CHOKED)); 
1168                if (peerInfo.flags & lbt::peer_info::remote_interested)
1169                        status_vec.push_back(app().res_wstr(HAL_PEER_REMOTE_INTERESTING));     
1170                if (peerInfo.flags & lbt::peer_info::remote_choked)
1171                        status_vec.push_back(app().res_wstr(HAL_PEER_REMOTE_CHOKED));   
1172                if (peerInfo.flags & lbt::peer_info::supports_extensions)
1173                        status_vec.push_back(app().res_wstr(HAL_PEER_SUPPORT_EXTENSIONS));     
1174        //      if (peerInfo.flags & lbt::peer_info::local_connection)                                          // Not sure whats up here?
1175        //              status_vec.push_back(app().res_wstr(HAL_PEER_LOCAL_CONNECTION));                       
1176                if (peerInfo.flags & lbt::peer_info::queued)
1177                        status_vec.push_back(app().res_wstr(HAL_PEER_QUEUED));
1178        }
1179       
1180        seed = (peerInfo.flags & lbt::peer_info::seed) ? true : false;
1181       
1182        if (!status_vec.empty()) status = status_vec[0];
1183       
1184        if (status_vec.size() > 1)
1185        {
1186                for (size_t i=1; i<status_vec.size(); ++i)
1187                {
1188                        status += L"; ";
1189                        status += status_vec[i];
1190                }
1191        }       
1192}
1193
1194void BitTorrent::getAllPeerDetails(string filename, PeerDetails& peerContainer)
1195{
1196        try {
1197       
1198        TorrentMap::iterator i = pimpl->torrents.find(filename);
1199       
1200        if (i != pimpl->torrents.end())
1201                (*i).second.getPeerDetails(peerContainer);
1202       
1203        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getAllPeerDetails")
1204}
1205
1206bool BitTorrent::isTorrent(string filename)
1207{       
1208        try {
1209       
1210        return (pimpl->torrents.find(filename) != pimpl->torrents.end());
1211       
1212        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "isTorrent")
1213       
1214        return false;
1215}
1216
1217void BitTorrent::pauseTorrent(string filename)
1218{
1219        try {
1220       
1221        TorrentMap::iterator i = pimpl->torrents.find(filename);
1222       
1223        if (i != pimpl->torrents.end())
1224        {
1225                (*i).second.pause();
1226        }
1227       
1228        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "pauseTorrent")
1229}
1230
1231void BitTorrent::resumeTorrent(string filename)
1232{
1233        try {
1234       
1235        TorrentMap::iterator i = pimpl->torrents.find(filename);
1236       
1237        if (i != pimpl->torrents.end())
1238        {
1239                (*i).second.resume();
1240        }
1241       
1242        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "resumeTorrent")
1243}
1244
1245void BitTorrent::stopTorrent(string filename)
1246{
1247        try {
1248       
1249        TorrentMap::iterator i = pimpl->torrents.find(filename);
1250       
1251        if (i != pimpl->torrents.end())
1252        {
1253                (*i).second.stop();
1254        }
1255       
1256        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "stopTorrent")
1257}
1258
1259bool BitTorrent::isTorrentActive(string filename)
1260{
1261        try {
1262       
1263        TorrentMap::const_iterator i = pimpl->torrents.find(filename);
1264       
1265        if (i != pimpl->torrents.end())
1266        {
1267                return (*i).second.isActive();
1268        }
1269       
1270        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "isTorrentActive")
1271       
1272        return false; // ??? is this correct
1273}
1274
1275void BitTorrent::setTorrentLogin(std::string filename, std::wstring username, std::wstring password)
1276{
1277        try {
1278       
1279        TorrentMap::iterator i = pimpl->torrents.find(filename);
1280       
1281        if (i != pimpl->torrents.end())
1282        {
1283                (*i).second.setTrackerLogin(username, password);
1284        }
1285       
1286        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentLogin")
1287}
1288
1289std::pair<std::wstring, std::wstring>  BitTorrent::getTorrentLogin(std::string filename)
1290{
1291        try {
1292       
1293        TorrentMap::iterator i = pimpl->torrents.find(filename);
1294       
1295        if (i != pimpl->torrents.end())
1296        {
1297                return (*i).second.getTrackerLogin();
1298        }
1299       
1300        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentLogin")
1301       
1302        return std::make_pair(L"", L"");
1303}
1304
1305void BitTorrent_impl::removalThread(lbt::torrent_handle handle, bool wipeFiles)
1306{
1307        try {
1308       
1309        if (!wipeFiles)
1310                theSession.remove_torrent(handle);
1311        else
1312        {
1313                fs::path saveDirectory = handle.save_path();
1314                lbt::torrent_info info = handle.get_torrent_info();
1315               
1316                theSession.remove_torrent(handle);
1317               
1318                foreach (const lbt::file_entry& entry, make_pair(info.begin_files(), info.end_files()))
1319                {
1320                        path file_path = saveDirectory / entry.path;
1321                       
1322                        if (exists(file_path) && !file_path.empty())
1323                                remove_all(file_path);
1324                }
1325               
1326                if (info.num_files() != 1)
1327                {
1328                        path dir_path = saveDirectory / info.name();
1329                        if (exists(dir_path) && is_empty(dir_path))
1330                                remove_all(dir_path);
1331                }
1332        }       
1333       
1334        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "removalThread")
1335}
1336
1337void BitTorrent::removeTorrent(string filename)
1338{
1339        try {
1340       
1341        TorrentMap::iterator i = pimpl->torrents.find(filename);
1342       
1343        if (i != pimpl->torrents.end())
1344        {
1345                lbt::torrent_handle handle = (*i).second.handle();
1346                pimpl->torrents.erase(i);
1347                thread t(bind(&BitTorrent_impl::removalThread, &*pimpl, handle, false));
1348        }
1349       
1350        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "removeTorrent")
1351}
1352
1353void BitTorrent::removeTorrentWipeFiles(string filename)
1354{
1355        try {
1356       
1357        TorrentMap::iterator i = pimpl->torrents.find(filename);
1358       
1359        if (i != pimpl->torrents.end())
1360        {
1361                lbt::torrent_handle handle = (*i).second.handle();
1362                pimpl->torrents.erase(i);
1363                thread t(bind(&BitTorrent_impl::removalThread, &*pimpl, handle, true));
1364        }
1365       
1366        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "removeTorrentWipeFiles")
1367}
1368
1369void BitTorrent::reannounceTorrent(string filename)
1370{
1371        try {
1372       
1373        TorrentMap::iterator i = pimpl->torrents.find(filename);
1374       
1375        if (i != pimpl->torrents.end())
1376        {
1377                (*i).second.handle().force_reannounce();
1378        }
1379       
1380        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "reannounceTorrent")
1381
1382//      pimpl->theSession.add_dht_node(make_pair(string("192.168.11.4"),6881));
1383//      Temporary Hijack
1384
1385/*      ofstream out("dump.txt");
1386       
1387        lbt::entry ent = pimpl->theSession.dht_state();
1388        lbt::entry::dictionary_type dic = ent.dict();
1389       
1390        for (lbt::entry::dictionary_type::iterator j = dic.begin();
1391                j != dic.end(); ++j)
1392        {
1393                out << (*j).first << " " << (*j).second << std::endl;
1394        }               
1395*/     
1396}
1397
1398void BitTorrent::pauseAllTorrents()
1399{       
1400        try {
1401       
1402        for (TorrentMap::iterator iter = pimpl->torrents.begin(); 
1403                iter != pimpl->torrents.end(); ++iter)
1404        {               
1405                if ((*iter).second.inSession())
1406                        (*iter).second.pause();
1407        }
1408       
1409        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "pauseAllTorrents")
1410}
1411
1412void BitTorrent::unpauseAllTorrents()
1413{       
1414        try {
1415       
1416        for (TorrentMap::iterator iter = pimpl->torrents.begin(); 
1417                iter != pimpl->torrents.end(); ++iter)
1418        {
1419                if ((*iter).second.inSession() && iter->second.state() == TorrentDetail::torrent_paused)
1420                        (*iter).second.resume();
1421        }
1422       
1423        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "unpauseAllTorrents")
1424}
1425
1426void BitTorrent::setTorrentLimit(string filename, int maxConn, int maxUpload)
1427{
1428        try {
1429       
1430        TorrentMap::iterator i = pimpl->torrents.find(filename);
1431       
1432        if (i != pimpl->torrents.end())
1433        {
1434                (*i).second.setConnectionLimit(maxConn, maxUpload);
1435        }
1436       
1437        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentLimit")
1438}
1439
1440void BitTorrent::setTorrentRatio(string filename, float ratio)
1441{
1442        try {
1443       
1444        TorrentMap::iterator i = pimpl->torrents.find(filename);
1445       
1446        if (i != pimpl->torrents.end())
1447        {
1448                (*i).second.setRatio(ratio);
1449        }
1450       
1451        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentRatio")
1452}
1453
1454float BitTorrent::getTorrentRatio(string filename)
1455{
1456        try {
1457       
1458        TorrentMap::iterator i = pimpl->torrents.find(filename);
1459       
1460        if (i != pimpl->torrents.end())
1461        {
1462                return (*i).second.getRatio();
1463        }
1464       
1465        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentRatio")
1466       
1467        return 0;
1468}
1469
1470void BitTorrent::setTorrentSpeed(string filename, float download, float upload)
1471{
1472        try {
1473       
1474        TorrentMap::iterator i = pimpl->torrents.find(filename);
1475       
1476        if (i != pimpl->torrents.end())
1477        {
1478                (*i).second.setTransferSpeed(download, upload);
1479        }
1480       
1481        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentSpeed")
1482}
1483
1484pair<int, int> BitTorrent::getTorrentLimit(string filename)
1485{
1486        try {
1487       
1488        TorrentMap::iterator i = pimpl->torrents.find(filename);
1489       
1490        if (i != pimpl->torrents.end())
1491        {
1492                return (*i).second.getConnectionLimit();
1493        }
1494       
1495        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentLimit")
1496       
1497        return pair<int, int>(0, 0);
1498}
1499
1500pair<float, float> BitTorrent::getTorrentSpeed(string filename)
1501{
1502        try {
1503       
1504        TorrentMap::iterator i = pimpl->torrents.find(filename);
1505       
1506        if (i != pimpl->torrents.end())
1507        {
1508                return (*i).second.getTransferSpeed();
1509        }
1510       
1511        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentSpeed")
1512       
1513        return pair<float, float>(0, 0);
1514}
1515
1516void BitTorrent::setTorrentTrackers(std::string filename, 
1517        const std::vector<TrackerDetail>& trackers)
1518{
1519        try {
1520       
1521        TorrentMap::iterator i = pimpl->torrents.find(filename);
1522       
1523        if (i != pimpl->torrents.end())
1524        {
1525                (*i).second.setTrackers(trackers);
1526        }
1527       
1528        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "setTorrentTrackers")
1529}
1530
1531void BitTorrent::resetTorrentTrackers(std::string filename)
1532{
1533        try {
1534       
1535        TorrentMap::iterator i = pimpl->torrents.find(filename);
1536       
1537        if (i != pimpl->torrents.end())
1538        {
1539                (*i).second.resetTrackers();
1540        }
1541       
1542        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "resetTorrentTrackers")
1543}
1544
1545std::vector<TrackerDetail> BitTorrent::getTorrentTrackers(std::string filename)
1546{
1547        try {
1548       
1549        TorrentMap::iterator i = pimpl->torrents.find(filename);
1550       
1551        if (i != pimpl->torrents.end())
1552        {
1553                return (*i).second.getTrackers();
1554        }
1555       
1556        } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "getTorrentTrackers")
1557       
1558        return std::vector<TrackerDetail>();   
1559}
1560
1561void BitTorrent::startEventReceiver()
1562{
1563        pimpl->keepChecking_ = true;
1564        thread(bind(&asio::io_service::run, &pimpl->io_));
1565}
1566
1567void BitTorrent::stopEventReceiver()
1568{
1569        pimpl->keepChecking_ = false;
1570}
1571
1572int BitTorrent::defTorrentMaxConn() { return pimpl->defTorrentMaxConn_; }
1573int BitTorrent::defTorrentMaxUpload() { return pimpl->defTorrentMaxUpload_; }
1574float BitTorrent::defTorrentDownload() { return pimpl->defTorrentDownload_; }
1575float BitTorrent::defTorrentUpload() { return pimpl->defTorrentUpload_; }
1576       
1577};
Note: See TracBrowser for help on using the repository browser.