source: src/halTorrent.cpp @ 268

Revision 268, 40.5 KB checked in by Eoin, 13 years ago (diff)

Added copyright eventually.

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