source: trunk/src/halTorrentInternal.cpp @ 696

Revision 696, 12.4 KB checked in by kavika, 11 years ago (diff)

Refactored some torrent_internal code to a cpp file.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2009.
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 "halTorrentInternal.hpp"
10
11namespace hal
12{
13
14void torrent_internal::adjust_queue_position(bit::queue_adjustments adjust)
15{
16        if (in_session() && is_managed())
17        {
18                switch (adjust)
19                {
20                case bit::move_up:
21                        handle_.queue_position_up();
22                        break;
23                case bit::move_down:
24                        handle_.queue_position_down();
25                        break;
26                case bit::move_to_top:
27                        handle_.queue_position_top();
28                        break;
29                case bit::move_to_bottom:
30                        handle_.queue_position_bottom();
31                        break;
32                };
33        }
34}
35
36void torrent_internal::add_to_session(bool paused)
37{
38        try
39        {
40        HAL_DEV_MSG(hal::wform(L"add_to_session() paused=%1%") % paused);
41
42        mutex_t::scoped_lock l(mutex_); 
43
44        process_event(ev_add_to_session(paused));
45        assert(in_session());
46
47        }
48        catch(std::exception& e)
49        {
50                hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
51                        new hal::EventStdException(event_logger::critical, e, L"add_to_session"))); 
52        }
53}
54
55bool torrent_internal::remove_from_session(bool write_data)
56{
57        try
58        {
59        HAL_DEV_MSG(hal::wform(L"remove_from_session() write_data=%1%") % write_data);
60
61        mutex_t::scoped_lock l(mutex_);
62       
63        process_event(ev_remove_from_session(write_data));
64        assert(in_session());
65
66        }
67        catch(std::exception& e)
68        {
69                hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
70                        new hal::EventStdException(event_logger::critical, e, L"remove_from_session()"))); 
71                return false;
72        }
73
74        return true;
75}
76
77torrent_details_ptr torrent_internal::get_torrent_details_ptr()
78{       
79        mutex_t::scoped_lock l(mutex_);
80
81        try
82        {
83
84        if (in_session())
85        {
86                status_memory_ = handle_.status();
87                progress_ = status_memory_.progress;
88
89                queue_position_ = handle_.queue_position();
90        }
91        else
92        {
93                // Wipe these cause they don't make sense for a non-active torrent.
94               
95                status_memory_.download_payload_rate = 0;
96                status_memory_.upload_payload_rate = 0;
97                status_memory_.next_announce = boost::posix_time::seconds(0);           
98        }
99       
100        wstring state_str;
101       
102        switch (state())
103        {
104        case torrent_details::torrent_paused:
105                state_str = app().res_wstr(HAL_TORRENT_PAUSED);
106                break;
107               
108        case torrent_details::torrent_pausing:
109                state_str = app().res_wstr(HAL_TORRENT_PAUSING);
110                break;
111               
112        case torrent_details::torrent_stopped:
113                state_str = app().res_wstr(HAL_TORRENT_STOPPED);
114                break;
115               
116        case torrent_details::torrent_stopping:
117                state_str = app().res_wstr(HAL_TORRENT_STOPPING);
118                break;
119               
120        case torrent_details::torrent_in_error:
121                state_str = app().res_wstr(HAL_TORRENT_IN_ERROR);
122                break;
123               
124        default:
125                switch (status_memory_.state)
126                {
127                case libt::torrent_status::queued_for_checking:
128                        state_str = app().res_wstr(HAL_TORRENT_QUEUED_CHECKING);
129                        break;
130                case libt::torrent_status::checking_files:
131                        state_str = app().res_wstr(HAL_TORRENT_CHECKING_FILES);
132                        break;
133//                      case libt::torrent_status::connecting_to_tracker:
134//                              state = app().res_wstr(HAL_TORRENT_CONNECTING);
135//                              break;
136                case libt::torrent_status::downloading_metadata:
137                        state_str = app().res_wstr(HAL_TORRENT_METADATA);
138                        break;
139                case libt::torrent_status::downloading:
140                        state_str = app().res_wstr(HAL_TORRENT_DOWNLOADING);
141                        break;
142                case libt::torrent_status::finished:
143                        state_str = app().res_wstr(HAL_TORRENT_FINISHED);
144                        break;
145                case libt::torrent_status::seeding:
146                        state_str = app().res_wstr(HAL_TORRENT_SEEDING);
147                        break;
148                case libt::torrent_status::allocating:
149                        state_str = app().res_wstr(HAL_TORRENT_ALLOCATING);
150                        break;
151                }       
152        }
153       
154        pt::time_duration td(pt::pos_infin);
155       
156        if (status_memory_.download_payload_rate != 0)
157        {
158                td = boost::posix_time::seconds(       
159                        long(float(status_memory_.total_wanted-status_memory_.total_wanted_done) / status_memory_.download_payload_rate));
160        }
161       
162        total_uploaded_ += (status_memory_.total_payload_upload - total_base_);
163        total_base_ = status_memory_.total_payload_upload;
164       
165        uploaded_.update(status_memory_.total_upload);
166        payload_uploaded_.update(status_memory_.total_payload_upload);
167        downloaded_.update(status_memory_.total_download);
168        payload_downloaded_.update(status_memory_.total_payload_download);
169       
170        if (is_active())
171        {
172                active_duration_.update();
173               
174                if (libt::torrent_status::seeding == status_memory_.state)
175                        seeding_duration_.update();
176        }       
177       
178        boost::tuple<size_t, size_t, size_t, size_t> connections = update_peers();     
179
180        return torrent_details_ptr(new torrent_details(
181                name_, filename_, 
182                save_directory().string(), 
183                state_str, 
184                hal::from_utf8(status_memory_.current_tracker), 
185                std::pair<float, float>(
186                        status_memory_.download_payload_rate, 
187                        status_memory_.upload_payload_rate),
188                progress_, 
189                status_memory_.distributed_copies, 
190                status_memory_.total_wanted_done, 
191                status_memory_.total_wanted, 
192                uploaded_, payload_uploaded_,
193                downloaded_, payload_downloaded_, 
194                connections, 
195                ratio_, 
196                td, 
197                status_memory_.next_announce, 
198                active_duration_, seeding_duration_, 
199                start_time_, finish_time_, 
200                queue_position_,
201                is_managed()));
202
203        }
204        catch (const libt::invalid_handle&)
205        {
206                event_log.post(shared_ptr<EventDetail>(
207                        new EventInvalidTorrent(event_logger::critical, 
208                                event_logger::invalid_torrent, to_utf8(name_), "get_torrent_details_ptr")));
209        }
210        catch (const std::exception& e)
211        {
212                event_log.post(shared_ptr<EventDetail>(
213                        new EventTorrentException(event_logger::critical, 
214                                event_logger::torrentException, e.what(), to_utf8(name_), "get_torrent_details_ptr")));
215        }
216       
217        return torrent_details_ptr(new torrent_details(
218                name_, filename_, 
219                save_directory().string(), 
220                app().res_wstr(HAL_TORRENT_STOPPED), 
221                app().res_wstr(HAL_NA)));
222}
223
224void torrent_internal::get_file_details(file_details_vec& files)
225{
226        if (file_details_memory_.empty())
227        {
228                boost::intrusive_ptr<libt::torrent_info> info = info_memory();
229                std::vector<libt::file_entry> files;
230               
231                std::copy(info->begin_files(), info->end_files(), 
232                        std::back_inserter(files));                                     
233                       
234                if (file_priorities_.size() != files.size())
235                {
236                        file_priorities_.clear();
237                        file_priorities_.assign(files.size(), 1);
238                }
239               
240                for(size_t i=0, e=files.size(); i<e; ++i)
241                {
242                        wstring fullPath = hal::from_utf8(files[i].path.string());
243                        boost::int64_t size = static_cast<boost::int64_t>(files[i].size);
244                       
245                        file_details_memory_.push_back(file_details(fullPath, size, 0, file_priorities_[i], i));
246                }       
247        }               
248       
249        if (in_session())
250        {                       
251                std::vector<libt::size_type> fileProgress;                     
252                handle_.file_progress(fileProgress);
253               
254                for(size_t i=0, e=file_details_memory_.size(); i<e; ++i)
255                        file_details_memory_[i].progress =  fileProgress[i];                   
256        }
257
258        for(size_t i=0, e=file_details_memory_.size(); i<e; ++i)
259                file_details_memory_[i].priority =  file_priorities_[i];
260       
261        files = file_details_memory_;
262}
263
264void torrent_internal::prepare(wpath filename)
265{
266        mutex_t::scoped_lock l(mutex_);
267       
268        if (fs::exists(filename)) 
269                info_memory_ = new libt::torrent_info(path_to_utf8(filename));
270       
271        extract_names(info_memory());                   
272       
273        const wpath resumeFile = hal::app().get_working_directory()/L"resume"/filename_;
274        const wpath torrentFile = hal::app().get_working_directory()/L"torrents"/filename_;
275       
276        event_log.post(shared_ptr<EventDetail>(new EventMsg(
277                hal::wform(L"File: %1%, %2%.") % resumeFile % torrentFile)));
278       
279//      if (exists(resumeFile))
280//              resumedata_ = haldecode(resumeFile);
281
282        if (!exists(hal::app().get_working_directory()/L"torrents"))
283                create_directory(hal::app().get_working_directory()/L"torrents");
284
285        if (!exists(torrentFile))
286                copy_file(filename.string(), torrentFile);
287
288        if (!fs::exists(save_directory_))
289                fs::create_directory(save_directory_);
290
291        // These here should not make state changes based on torrent
292        // session status since it has not been initialized yet.
293        if (state_ == torrent_details::torrent_stopping)
294                state(torrent_details::torrent_stopped);
295        else if (state_ == torrent_details::torrent_pausing)
296                state(torrent_details::torrent_paused);
297}
298
299void torrent_internal::extract_names(boost::intrusive_ptr<libt::torrent_info> metadata)
300{
301        mutex_t::scoped_lock l(mutex_);
302                       
303        name_ = hal::from_utf8_safe(metadata->name());
304       
305        filename_ = name_;
306        if (!boost::find_last(filename_, L".torrent")) 
307                        filename_ += L".torrent";
308       
309        event_log.post(shared_ptr<EventDetail>(new EventMsg(
310                hal::wform(L"Loaded names: %1%, %2%") % name_ % filename_)));
311}
312
313boost::tuple<size_t, size_t, size_t, size_t> torrent_internal::update_peers()
314{
315        if (in_session())
316                handle_.get_peer_info(peers_);
317       
318        size_t totalPeers = 0;
319        size_t peersConnected = 0;
320        size_t totalSeeds = 0;
321        size_t seedsConnected = 0;
322       
323        foreach (libt::peer_info& peer, peers_) 
324        {
325                float speedSum = peer.down_speed + peer.up_speed;
326               
327                if (!(peer.flags & libt::peer_info::seed))
328                {
329                        ++totalPeers;
330                       
331                        if (speedSum > 0)
332                                ++peersConnected;
333                }
334                else
335                {
336                        ++totalSeeds;
337                       
338                        if (speedSum > 0)
339                                ++seedsConnected;
340                }
341        }       
342       
343        return boost::make_tuple(totalPeers, peersConnected, totalSeeds, seedsConnected);
344}
345
346// ----------------- private -----------------
347
348void torrent_internal::apply_settings()
349{               
350        apply_transfer_speed();
351        apply_connection_limit();
352        apply_ratio();
353        apply_trackers();
354        apply_tracker_login();
355        apply_file_priorities();
356        apply_resolve_countries();
357}
358
359void torrent_internal::apply_transfer_speed()
360{
361        mutex_t::scoped_lock l(mutex_);
362        if (in_session())
363        {
364                int down = (transfer_limit_.first > 0) ? static_cast<int>(transfer_limit_.first*1024) : -1;
365                handle_.set_download_limit(down);
366               
367                int up = (transfer_limit_.second > 0) ? static_cast<int>(transfer_limit_.second*1024) : -1;
368                handle_.set_upload_limit(up);
369
370                HAL_DEV_MSG(hal::wform(L"Applying Transfer Speed %1% - %2%") % down % up);
371        }
372}
373
374void torrent_internal::apply_connection_limit()
375{
376        mutex_t::scoped_lock l(mutex_);
377        if (in_session())
378        {
379                handle_.set_max_connections(connections_);
380                handle_.set_max_uploads(uploads_);
381
382                HAL_DEV_MSG(hal::wform(L"Applying Connection Limit %1% - %2%") % connections_ % uploads_);
383        }
384}
385
386void torrent_internal::apply_ratio()
387{ 
388        mutex_t::scoped_lock l(mutex_);
389        if (in_session())
390        {
391                handle_.set_ratio(ratio_);
392
393                HAL_DEV_MSG(hal::wform(L"Applying Ratio %1%") % ratio_);
394        }
395}
396
397void torrent_internal::apply_trackers()
398{
399        mutex_t::scoped_lock l(mutex_);
400        if (in_session())
401        {
402                if (torrent_trackers_.empty())
403                        torrent_trackers_ = handle_.trackers();
404               
405                if (!trackers_.empty())
406                {
407                        std::vector<libt::announce_entry> trackers;
408                       
409                        foreach (const tracker_detail& tracker, trackers_)
410                        {
411                                trackers.push_back(
412                                        libt::announce_entry(hal::to_utf8(tracker.url)));
413                                trackers.back().tier = tracker.tier;
414                        }
415                        handle_.replace_trackers(trackers);
416                }
417               
418                HAL_DEV_MSG(L"Applying Trackers");
419        }
420}
421
422void torrent_internal::apply_tracker_login()
423{
424        mutex_t::scoped_lock l(mutex_);
425        if (in_session())
426        {
427                if (tracker_username_ != L"")
428                {
429                        handle_.set_tracker_login(hal::to_utf8(tracker_username_),
430                                hal::to_utf8(tracker_password_));
431                }
432
433                HAL_DEV_MSG(hal::wform(L"Applying Tracker Login User: %1%, Pass: %2%")
434                        % tracker_username_ % tracker_password_ );
435        }
436}
437
438void torrent_internal::apply_file_priorities()
439{               
440        mutex_t::scoped_lock l(mutex_);
441        if (in_session()) 
442        {
443                if (!file_priorities_.empty())
444                        handle_.prioritize_files(file_priorities_);
445               
446                HAL_DEV_MSG(L"Applying File Priorities");
447        }
448}       
449
450void torrent_internal::apply_resolve_countries()
451{
452        mutex_t::scoped_lock l(mutex_);
453        if (in_session())
454        {
455                handle_.resolve_countries(resolve_countries_);
456               
457                HAL_DEV_MSG(hal::wform(L"Applying Resolve Countries %1%") % resolve_countries_);
458        }
459}
460
461void torrent_internal::state(unsigned s)
462{
463        switch (s)
464        {
465        case torrent_details::torrent_stopped:
466                HAL_DEV_MSG(L"state() - stopped");
467                break;
468        case torrent_details::torrent_stopping:
469                HAL_DEV_MSG(L"state() - stopping");
470                break;
471        case torrent_details::torrent_pausing:
472                HAL_DEV_MSG(L"state() - pausing");
473                break;
474        case torrent_details::torrent_active:
475                HAL_DEV_MSG(L"state() - active");
476                break;
477        case torrent_details::torrent_paused:
478                HAL_DEV_MSG(L"state() - paused");
479                break;
480        case torrent_details::torrent_in_error:
481                HAL_DEV_MSG(L"state() - in error");
482                break;
483        default:
484                HAL_DEV_MSG(L"state() - unknown");
485                break;
486        };
487        state_ = s;
488}
489
490};
Note: See TracBrowser for help on using the repository browser.