source: trunk/src/halSession.cpp @ 503

Revision 503, 17.3 KB checked in by Eoin, 11 years ago (diff)

Cleaned up trunk alert handler code.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2008.
3// Distributed under the Boost Software License, Version 1.0.
4//    (See accompanying file LICENSE_1_0.txt or copy at
5//          http://www.boost.org/LICENSE_1_0.txt)
6
7#include "stdAfx.hpp"
8
9#define TORRENT_MAX_ALERT_TYPES 32
10
11#include <boost/utility/in_place_factory.hpp>
12#include <boost/none.hpp>
13
14#include <libtorrent/alert_types.hpp>
15#include <libtorrent/entry.hpp>
16#include <libtorrent/session.hpp>
17#include <libtorrent/ip_filter.hpp>
18#include <libtorrent/torrent_handle.hpp>
19
20#include "global/wtl_app.hpp"
21#include "global/string_conv.hpp"
22#include "global/ini_adapter.hpp"
23
24#include "halIni.hpp"
25#include "halTypes.hpp"
26#include "halEvent.hpp"
27#include "halSignaler.hpp"
28#include "halSession.hpp"
29
30namespace hal
31{
32
33bit_impl::bit_impl() :
34        session_(libt::fingerprint(HALITE_FINGERPRINT)),
35        keepChecking_(false),
36        bittorrentIni(L"BitTorrent.xml"),
37        the_torrents_(bittorrentIni),
38        defTorrentMaxConn_(-1),
39        defTorrentMaxUpload_(-1),
40        defTorrentDownload_(-1),
41        defTorrentUpload_(-1),
42        ip_filter_on_(false),
43        ip_filter_loaded_(false),
44        ip_filter_changed_(false),
45        ip_filter_count_(0),
46        dht_on_(false)
47{
48        torrent_internal::the_session_ = &session_;
49        torrent_internal::workingDir_ = workingDir();
50       
51        session_.set_severity_level(libt::alert::debug);               
52        session_.add_extension(&libt::create_metadata_plugin);
53        session_.add_extension(&libt::create_ut_pex_plugin);
54        session_.set_max_half_open_connections(10);
55       
56        hal::event_log.post(shared_ptr<hal::EventDetail>(
57                new hal::EventMsg(L"Loading BitTorrent.xml.", hal::event_logger::info)));               
58        bittorrentIni.load_data();
59        hal::event_log.post(shared_ptr<hal::EventDetail>(
60                new hal::EventMsg(L"Loading torrent parameters.", hal::event_logger::info)));   
61        the_torrents_.load_from_ini();
62        hal::event_log.post(shared_ptr<hal::EventDetail>(
63                new hal::EventMsg(L"Loading done!", hal::event_logger::info)));
64       
65        try
66        {                                               
67        if (fs::exists(workingDirectory/L"Torrents.xml"))
68        {
69                {
70                fs::wifstream ifs(workingDirectory/L"Torrents.xml");
71       
72                event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Loading old Torrents.xml")));
73       
74                TorrentMap torrents;
75                boost::archive::xml_wiarchive ia(ifs); 
76                ia >> boost::serialization::make_nvp("torrents", torrents);
77               
78                the_torrents_ = torrents;
79                }
80               
81                event_log.post(shared_ptr<EventDetail>(new EventMsg(
82                        wformat(L"Total %1%.") % the_torrents_.size())));                               
83               
84                fs::rename(workingDirectory/L"Torrents.xml", workingDirectory/L"Torrents.xml.safe.to.delete");
85        }                       
86        }
87        catch(const std::exception& e)
88        {
89                event_log.post(shared_ptr<EventDetail>(
90                        new EventStdException(event_logger::fatal, e, L"Loading Old Torrents.xml")));
91        }               
92                       
93        if (exists(workingDirectory/L"DHTState.bin"))
94        {
95                try
96                {
97                        dht_state_ = haldecode(workingDirectory/L"DHTState.bin");
98                }               
99                catch(const std::exception& e)
100                {
101                        event_log.post(shared_ptr<EventDetail>(
102                                new EventStdException(event_logger::critical, e, L"Loading DHTState.bin")));
103                }
104        }
105       
106        {       libt::session_settings settings = session_.settings();
107                settings.user_agent = string("Halite ") + HALITE_VERSION_STRING;
108                session_.set_settings(settings);
109        }
110       
111        start_alert_handler();
112}
113
114bit_impl::~bit_impl()
115{
116        stop_alert_handler();
117       
118        //save_torrent_data();
119       
120        try
121        {
122       
123        if (ip_filter_changed_)
124        {       
125                fs::ofstream ofs(workingDirectory/L"IPFilter.bin", std::ios::binary);
126//                      boost::archive::binary_oarchive oba(ofs);
127               
128                libt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();   
129               
130                std::vector<libt::ip_range<asio::ip::address_v4> > v4(vectors.get<0>());
131                std::vector<libt::ip_range<asio::ip::address_v6> > v6(vectors.get<1>());
132               
133                v4.erase(std::remove(v4.begin(), v4.end(), 0), v4.end());
134                v6.erase(std::remove(v6.begin(), v6.end(), 0), v6.end());
135
136                write_vec_range(ofs, v4);
137//                      write_vec_range(ofs, v6);
138        }       
139        }
140        catch(std::exception& e)
141        {
142                hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
143                        new hal::EventStdException(event_logger::critical, e, L"~BitTorrent_impl"))); 
144        }
145}
146
147void bit_impl::ip_filter_count()
148{
149        libt::ip_filter::filter_tuple_t vectors = ip_filter_.export_filter();
150       
151        vectors.get<0>().erase(std::remove(vectors.get<0>().begin(), vectors.get<0>().end(), 0),
152                vectors.get<0>().end());
153        vectors.get<1>().erase(std::remove(vectors.get<1>().begin(), vectors.get<1>().end(), 0),
154                vectors.get<1>().end());
155        ip_filter_count_ = vectors.get<0>().size() + vectors.get<1>().size();
156}
157
158void bit_impl::ip_filter_load(progress_callback fn)
159{
160        fs::ifstream ifs(workingDirectory/L"IPFilter.bin", std::ios::binary);
161        if (ifs)
162        {
163                size_t v4_size;
164                ifs >> v4_size;
165               
166                size_t total = v4_size/100;
167                size_t previous = 0;
168               
169                for(unsigned i=0; i<v4_size; ++i)
170                {
171                        if (i-previous > total)
172                        {
173                                previous = i;
174
175                                if (fn) if (fn(size_t(i/total), hal::app().res_wstr(HAL_TORRENT_LOAD_FILTERS))) break;
176                        }
177                       
178                        read_range_to_filter<asio::ip::address_v4>(ifs, ip_filter_);
179                }
180        }       
181}
182
183void  bit_impl::ip_filter_import(std::vector<libt::ip_range<asio::ip::address_v4> >& v4,
184        std::vector<libt::ip_range<asio::ip::address_v6> >& v6)
185{
186        for(std::vector<libt::ip_range<asio::ip::address_v4> >::iterator i=v4.begin();
187                i != v4.end(); ++i)
188        {
189                ip_filter_.add_rule(i->first, i->last, libt::ip_filter::blocked);
190        }
191/*      for(std::vector<libt::ip_range<asio::ip::address_v6> >::iterator i=v6.begin();
192                i != v6.end(); ++i)
193        {
194                ip_filter_.add_rule(i->first, i->last, libt::ip_filter::blocked);
195        }
196*/     
197        /* Note here we do not set ip_filter_changed_ */
198}
199
200bool bit_impl::ip_filter_import_dat(boost::filesystem::path file, progress_callback fn, bool octalFix)
201{
202        try
203        {
204
205        fs::ifstream ifs(file); 
206        if (ifs)
207        {
208                boost::uintmax_t total = fs::file_size(file)/100;
209                boost::uintmax_t progress = 0;
210                boost::uintmax_t previous = 0;
211               
212                boost::regex reg("\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*-\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*.*");
213                boost::regex ip_reg("0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)\\.0*(\\d*)");
214                boost::smatch m;
215               
216                string ip_address_line;         
217                while (!std::getline(ifs, ip_address_line).eof())
218                {               
219                        progress += (ip_address_line.length() + 2);
220                        if (progress-previous > total)
221                        {
222                                previous = progress;
223                                if (fn)
224                                {
225                                        if (fn(size_t(progress/total), hal::app().res_wstr(HAL_TORRENT_IMPORT_FILTERS))) 
226                                                break;
227                                }
228                        }
229                       
230                        if (boost::regex_match(ip_address_line, m, reg))
231                        {
232                                string first = m[1];
233                                string last = m[2];
234                               
235                                if (octalFix)
236                                {
237                                        if (boost::regex_match(first, m, ip_reg))
238                                        {
239                                                first = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
240                                                                ((m.length(2) != 0) ? m[2] : string("0")) + "." +
241                                                                ((m.length(3) != 0) ? m[3] : string("0")) + "." +
242                                                                ((m.length(4) != 0) ? m[4] : string("0"));
243                                        }                                       
244                                        if (boost::regex_match(last, m, ip_reg))
245                                        {
246                                                last = ((m.length(1) != 0) ? m[1] : string("0")) + "." +
247                                                           ((m.length(2) != 0) ? m[2] : string("0")) + "." +
248                                                           ((m.length(3) != 0) ? m[3] : string("0")) + "." +
249                                                           ((m.length(4) != 0) ? m[4] : string("0"));
250                                        }
251                                }
252                               
253                                try
254                                {                       
255                                ip_filter_.add_rule(asio::ip::address_v4::from_string(first),
256                                        asio::ip::address_v4::from_string(last), libt::ip_filter::blocked);     
257                                }
258                                catch(...)
259                                {
260                                        hal::event_log.post(shared_ptr<hal::EventDetail>(
261                                                new hal::EventDebug(hal::event_logger::info, 
262                                                        from_utf8((format("Invalid IP range: %1%-%2%.") % first % last).str()))));
263                                }
264                        }
265                }
266        }
267       
268        ip_filter_changed_ = true;
269        ip_filter_count();
270       
271        }
272        catch(const std::exception& e)
273        {
274                event_log.post(shared_ptr<EventDetail>(
275                        new EventStdException(event_logger::critical, e, L"ip_filter_import_dat")));
276        }
277
278        return false;
279}
280
281void bit_impl::start_alert_handler()
282{
283        mutex_t::scoped_lock l(mutex_);
284
285        boost::function<void (void)> f = bind(&bit_impl::alert_handler, this);
286
287        keepChecking_ = true;
288        alert_checker_ = boost::in_place<boost::function<void (void)> >(bind(&bit_impl::alert_handler, this));
289}
290       
291void bit_impl::stop_alert_handler()
292{
293        mutex_t::scoped_lock l(mutex_);
294
295        keepChecking_ = false;
296
297        if (alert_checker_)
298        {
299                alert_checker_->interrupt();
300                alert_checker_ = boost::none;
301        }
302}
303       
304void bit_impl::alert_handler()
305{
306        while (keepChecking_)
307        {
308       
309        std::auto_ptr<libt::alert> p_alert = session_.pop_alert();
310       
311        class AlertHandler
312        {
313        public:
314        AlertHandler(bit_impl& bit_impl) :
315                bit_impl_(bit_impl)
316        {}
317
318        void operator()(libt::external_ip_alert const& a) const
319        {
320                event_log.post(shared_ptr<EventDetail>(
321                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
322                                wformat(hal::app().res_wstr(HAL_EXTERNAL_IP_ALERT))
323                                        % hal::from_utf8_safe(a.message())
324                                        % hal::from_utf8_safe(a.external_address.to_string()))
325                )       );                             
326        }
327
328        void operator()(libt::portmap_error_alert const& a) const
329        {
330                event_log.post(shared_ptr<EventDetail>(
331                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
332                                wformat(hal::app().res_wstr(HAL_PORTMAP_ERROR_ALERT))
333                                % (a.type == 0 ? 
334                                        hal::app().res_wstr(HAL_PORTMAP_TYPE_PMP) : 
335                                        hal::app().res_wstr(HAL_PORTMAP_TYPE_UPNP)))
336                )       );                             
337        }
338
339        void operator()(libt::portmap_alert const& a) const
340        {
341                event_log.post(shared_ptr<EventDetail>(
342                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
343                                wformat(hal::app().res_wstr(HAL_PORTMAP_ALERT))
344                                % (a.type == 0 ? 
345                                        hal::app().res_wstr(HAL_PORTMAP_TYPE_PMP) : 
346                                        hal::app().res_wstr(HAL_PORTMAP_TYPE_UPNP))
347                                % a.external_port)
348                )       );                             
349        }
350       
351        void operator()(libt::file_error_alert const& a) const
352        {
353                event_log.post(shared_ptr<EventDetail>(
354                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
355                                wformat(hal::app().res_wstr(HAL_FILE_ERROR_ALERT))
356                                % hal::from_utf8_safe(a.file)
357                                % hal::from_utf8_safe(a.msg))
358                )       );                             
359        }
360       
361        void operator()(libt::dht_reply_alert const& a) const
362        {
363                event_log.post(shared_ptr<EventDetail>(
364                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
365                                wformat(hal::app().res_wstr(HAL_DHT_REPLY_ALERT))
366                                        % a.num_peers)
367                )       );                             
368        }
369
370        void operator()(libt::torrent_finished_alert const& a) const
371        {
372                event_log.post(shared_ptr<EventDetail>(
373                        new EventMsg((wformat(hal::app().res_wstr(LBT_EVENT_TORRENT_FINISHED)) 
374                                        % get(a.handle)->name()), 
375                                event_logger::info, a.timestamp())));
376               
377                get(a.handle)->finished();     
378        }
379       
380        void operator()(libt::torrent_paused_alert const& a) const
381        {
382                event_log.post(shared_ptr<EventDetail>(
383                        new EventMsg((wformat(hal::app().res_wstr(LBT_EVENT_TORRENT_PAUSED)) 
384                                        % get(a.handle)->name()), 
385                                event_logger::info, a.timestamp())));
386
387                get(a.handle)->signals().torrent_paused();
388        }
389       
390        void operator()(libt::peer_error_alert const& a) const
391        {
392                event_log.post(shared_ptr<EventDetail>(
393                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
394                                wformat(hal::app().res_wstr(HAL_PEER_ALERT))
395                                        % hal::from_utf8_safe(a.message())
396                                        % hal::from_utf8_safe(a.ip.address().to_string()))
397                )       );                             
398        }
399               
400        void operator()(libt::peer_ban_alert const& a) const
401        {
402                event_log.post(shared_ptr<EventDetail>(
403                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
404                                wformat(hal::app().res_wstr(HAL_PEER_BAN_ALERT))
405                                        % get(a.handle)->name()
406                                        % hal::from_utf8_safe(a.ip.address().to_string()))
407                )       );                             
408        }
409               
410        void operator()(libt::hash_failed_alert const& a) const
411        {
412                event_log.post(shared_ptr<EventDetail>(
413                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
414                                wformat(hal::app().res_wstr(HAL_HASH_FAIL_ALERT))
415                                        % get(a.handle)->name()
416                                        % a.piece_index)
417                )       );                             
418        }
419               
420        void operator()(libt::url_seed_alert const& a) const
421        {
422                event_log.post(shared_ptr<EventDetail>(
423                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
424                                wformat(hal::app().res_wstr(HAL_URL_SEED_ALERT))
425                                        % get(a.handle)->name()
426                                        % hal::from_utf8_safe(a.url)
427                                        % hal::from_utf8_safe(a.message()))
428                )       );                             
429        }
430       
431        void operator()(libt::tracker_warning_alert const& a) const
432        {
433                event_log.post(shared_ptr<EventDetail>(
434                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
435                                wformat(hal::app().res_wstr(HAL_TRACKER_WARNING_ALERT))
436                                        % get(a.handle)->name()
437                                        % hal::from_utf8_safe(a.message()))
438                )       );                             
439        }
440       
441        void operator()(libt::tracker_announce_alert const& a) const
442        {
443                event_log.post(shared_ptr<EventDetail>(
444                        new EventMsg((wformat(hal::app().res_wstr(HAL_TRACKER_ANNOUNCE_ALERT)) 
445                                        % get(a.handle)->name()), 
446                                event_logger::info, a.timestamp())));
447        }
448       
449        void operator()(libt::tracker_error_alert const& a) const
450        {
451                event_log.post(shared_ptr<EventDetail>(
452                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
453                                wformat(hal::app().res_wstr(HAL_TRACKER_ALERT))
454                                        % get(a.handle)->name()
455                                        % hal::from_utf8_safe(a.message())
456                                        % a.times_in_row
457                                        % a.status_code)
458                )       );                             
459        }
460       
461        void operator()(libt::tracker_reply_alert const& a) const
462        {
463                event_log.post(shared_ptr<EventDetail>(
464                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
465                                wformat(hal::app().res_wstr(HAL_TRACKER_REPLY_ALERT))
466                                        % get(a.handle)->name()
467                                        % hal::from_utf8_safe(a.message())
468                                        % a.num_peers)
469                )       );                             
470        }
471       
472        void operator()(libt::fastresume_rejected_alert const& a) const
473        {
474                event_log.post(shared_ptr<EventDetail>(
475                        new EventGeneral(lbtAlertToHalEvent(a.severity()), a.timestamp(),
476                                wformat(hal::app().res_wstr(HAL_FAST_RESUME_ALERT))
477                                        % get(a.handle)->name()
478                                        % hal::from_utf8_safe(a.message()))
479                )       );                             
480        }
481       
482        void operator()(libt::piece_finished_alert const& a) const
483        {
484                event_log.post(shared_ptr<EventDetail>(
485                        new EventGeneral(event_logger::debug, a.timestamp(),
486                                wformat(hal::app().res_wstr(HAL_PIECE_FINISHED_ALERT))
487                                        % get(a.handle)->name()
488                                        % a.piece_index)
489                )       );                             
490        }
491       
492        void operator()(libt::block_finished_alert const& a) const
493        {
494                event_log.post(shared_ptr<EventDetail>(
495                        new EventGeneral(event_logger::debug, a.timestamp(),
496                                wformat(hal::app().res_wstr(HAL_BLOCK_FINISHED_ALERT))
497                                        % get(a.handle)->name()
498                                        % a.block_index
499                                        % a.piece_index)
500                )       );                             
501        }
502       
503        void operator()(libt::block_downloading_alert const& a) const
504        {
505                event_log.post(shared_ptr<EventDetail>(
506                        new EventGeneral(event_logger::debug, a.timestamp(),
507                                wformat(hal::app().res_wstr(HAL_BLOCK_DOWNLOADING_ALERT))
508                                        % get(a.handle)->name()
509                                        % a.block_index
510                                        % a.piece_index)
511                )       );                             
512        }
513       
514        void operator()(libt::listen_failed_alert const& a) const
515        {
516                if (a.endpoint.address().is_v6())
517                {       
518                        event_log.post(shared_ptr<EventDetail>(
519                                new EventGeneral(event_logger::info, a.timestamp(),
520                                        hal::app().res_wstr(HAL_LISTEN_V6_FAILED_ALERT))
521                        )       );             
522                }
523                else
524                {
525                        event_log.post(shared_ptr<EventDetail>(
526                                new EventGeneral(event_logger::info, a.timestamp(),
527                                        wformat(hal::app().res_wstr(HAL_LISTEN_FAILED_ALERT))
528                                                % hal::from_utf8_safe(a.message()))
529                        )       );
530                }
531        }
532       
533        void operator()(libt::listen_succeeded_alert const& a) const
534        {
535                event_log.post(shared_ptr<EventDetail>(
536                        new EventGeneral(event_logger::info, a.timestamp(),
537                                wformat(hal::app().res_wstr(HAL_LISTEN_SUCCEEDED_ALERT))
538                                        % hal::from_utf8_safe(a.message()))
539                )       );     
540
541                bit_impl_.signals.successful_listen();
542        }
543       
544        void operator()(libt::peer_blocked_alert const& a) const
545        {
546                event_log.post(shared_ptr<EventDetail>(
547                        new EventGeneral(event_logger::debug, a.timestamp(),
548                                wformat(hal::app().res_wstr(HAL_IPFILTER_ALERT))
549                                        % hal::from_utf8_safe(a.ip.to_string())
550                                        % hal::from_utf8_safe(a.message()))
551                )       );                             
552        }
553       
554        void operator()(libt::alert const& a) const
555        {
556                event_log.post(shared_ptr<EventDetail>(
557                                new EventLibtorrent(lbtAlertToHalEvent(a.severity()), 
558                                        a.timestamp(), event_logger::unclassified, hal::from_utf8_safe(a.message()))));         
559        }
560       
561        private:
562                bit_impl& bit_impl_;
563               
564                torrent_internal_ptr get(libt::torrent_handle h) const 
565                { 
566                        return bit_impl_.the_torrents_.get(from_utf8_safe(h.get_torrent_info().name())); 
567                }
568       
569        } handler(*this);
570       
571        while (p_alert.get())
572        {       
573                try
574                {
575                mutex_t::scoped_lock l(mutex_);
576               
577                libt::handle_alert<
578                        libt::external_ip_alert,
579                        libt::portmap_error_alert,
580                        libt::portmap_alert,
581                        libt::file_error_alert,
582                        libt::torrent_finished_alert,
583                        libt::torrent_paused_alert,
584                        libt::peer_error_alert,
585                        libt::peer_ban_alert,
586                        libt::hash_failed_alert,
587                        libt::url_seed_alert,
588                        libt::dht_reply_alert,
589                        libt::tracker_error_alert,
590                        libt::tracker_warning_alert,
591                        libt::tracker_announce_alert,
592                        libt::tracker_reply_alert,
593                        libt::fastresume_rejected_alert,
594                        libt::piece_finished_alert,
595                        libt::block_finished_alert,
596                        libt::block_downloading_alert,
597                        libt::listen_failed_alert,
598                        libt::listen_succeeded_alert,
599                        libt::peer_blocked_alert,
600                        libt::alert
601                >::handle_alert(p_alert, handler);                     
602               
603                }
604                catch(libt::unhandled_alert&)
605                {
606                        handler(*p_alert);
607                }
608                catch(std::exception& e)
609                {
610                        // These are logged as debug because they are rarely important to act on!
611                        event_log.post(shared_ptr<EventDetail>(\
612                                new EventStdException(event_logger::debug, e, L"alertHandler")));
613                }
614               
615                p_alert = session_.pop_alert();
616
617                boost::this_thread::sleep(boost::posix_time::seconds(5));
618        }       
619       
620        }
621}
622
623}
Note: See TracBrowser for help on using the repository browser.