source: src/halTorrentInternal.hpp @ 243

Revision 243, 11.5 KB checked in by Eoin, 13 years ago (diff)

ListView? sorting working but not complete.

Line 
1
2#pragma once
3
4namespace hal
5{
6class TorrentInternal;
7}
8
9BOOST_CLASS_VERSION(hal::TorrentInternal, 4)
10
11namespace hal
12{
13
14namespace lbt = libtorrent;
15namespace fs = boost::filesystem;
16
17using fs::path;
18using fs::ifstream;
19using fs::ofstream;
20using boost::serialization::make_nvp;
21
22class TorrentInternal
23{
24        friend class BitTorrent_impl;
25       
26        template<typename T>
27        class TransferTracker
28        {
29        public:
30                TransferTracker() :
31                        total_(0),
32                        total_offset_(0)
33                {}
34               
35                TransferTracker(T total) :
36                        total_(total),
37                        total_offset_(0)
38                {}
39               
40                void reset(T total) const
41                {
42                        total_ = total;
43                        total_offset_ = 0;
44                }
45               
46                T update(T rel_total) const
47                {
48                        total_ += (rel_total - total_offset_);
49                        total_offset_ = rel_total;
50                                               
51                        return total_;
52                }
53               
54                operator T() const { return total_; }
55               
56                friend class boost::serialization::access;
57                template<class Archive>
58                void serialize(Archive& ar, const unsigned int version)
59                {
60                        ar & make_nvp("total", total_);
61                }
62               
63        private:
64                mutable T total_;
65                mutable T total_offset_;
66        };
67       
68public:
69        TorrentInternal() :     
70                transferLimit_(std::pair<float, float>(-1, -1)),
71                connections_(-1),
72                uploads_(-1),
73                ratio_(0),
74                resolve_countries_(true),
75                state_(TorrentDetail::torrent_active),
76                in_session_(false),
77                totalUploaded_(0),
78                totalBase_(0)
79        {}
80       
81        TorrentInternal(libtorrent::torrent_handle h, std::wstring f, wpath saveDirectory) :
82                transferLimit_(std::pair<float, float>(bittorrent().defTorrentDownload(), bittorrent().defTorrentUpload())),
83                connections_(bittorrent().defTorrentMaxConn()),
84                uploads_(bittorrent().defTorrentMaxUpload()),
85                ratio_(0),
86                resolve_countries_(true),                            // **********
87                state_(TorrentDetail::torrent_active),
88                filename_(f),
89                save_directory_(saveDirectory.string()),
90                in_session_(true),
91                handle_(h),
92                totalUploaded_(0),
93                totalBase_(0)
94        {}
95       
96        TorrentDetail_ptr getTorrentDetail_ptr() const;
97        void setTransferSpeed(float down, float up);
98        void setConnectionLimit(int maxConn, int maxUpload);
99        void setTransferSpeed();
100        void setConnectionLimit();
101        pair<float, float> getTransferSpeed();
102        pair<int, int> getConnectionLimit();
103       
104        void setRatio(float ratio) 
105        { 
106                if (ratio < 0) ratio = 0;
107               
108                handle_.set_ratio(ratio);
109                ratio_ = ratio; 
110        }
111       
112        void setRatio()
113        {               
114                handle_.set_ratio(ratio_);
115        }
116       
117        float getRatio()
118        {
119                return ratio_;
120        }
121       
122        void setResolveCountries()
123        {
124                handle_.resolve_countries(resolve_countries_);
125        }
126       
127        void resume()
128        {
129                if (!in_session_ && the_session_) 
130                {
131                        handle_ = the_session_->add_torrent(metadata_, 
132                                to_utf8(save_directory_.c_str()), resumedata_);
133                               
134                        in_session_ = true;
135                        applySettings();
136                }               
137                assert(in_session_);
138               
139                handle_.resume();
140                state_ = TorrentDetail::torrent_active;
141        }
142       
143        void pause()
144        {
145                if (state_ != TorrentDetail::torrent_stopped)
146                {       
147                        if (!in_session_ && the_session_) 
148                        {
149                                handle_ = the_session_->add_torrent(metadata_, 
150                                        to_utf8(save_directory_.c_str()), resumedata_);
151                                       
152                                in_session_ = true;
153                                applySettings();
154                        }
155                        assert(in_session_);
156                       
157                        handle_.pause();
158                        state_ = TorrentDetail::torrent_paused; 
159                }
160        }
161       
162        void stop()
163        {
164                if (in_session_ && the_session_) 
165                {
166                        the_session_->remove_torrent(handle_);
167                        in_session_ = false;
168                }
169                assert(!in_session_);
170               
171                state_ = TorrentDetail::torrent_stopped;       
172        }
173       
174        bool isActive() const { return state_ == TorrentDetail::torrent_active; }
175       
176        unsigned state() const { return state_; }
177       
178        void setTrackerLogin()
179        {
180                if (trackerUsername_ != L"")
181                {
182                        handle_.set_tracker_login(hal::to_utf8(trackerUsername_),
183                                hal::to_utf8(trackerPassword_));
184                }
185        }
186       
187        void setTrackerLogin(wstring username, wstring password)
188        {
189                trackerUsername_ = username;
190                trackerPassword_ = password;
191                setTrackerLogin();
192        }       
193       
194        pair<wstring, wstring> getTrackerLogin() const
195        {
196                return make_pair(trackerUsername_, trackerPassword_);
197        }
198       
199        const std::wstring& filename() const { return filename_; }
200       
201        const libtorrent::torrent_handle& handle() const { return handle_; }
202
203        void setHandle(libtorrent::torrent_handle h) 
204        { 
205                handle_ = h; 
206                in_session_ = true;
207        }
208       
209        void resetTrackers()
210        {
211                handle_.replace_trackers(torrent_trackers_);           
212                trackers_.clear();     
213        }
214       
215        const std::vector<TrackerDetail>& getTrackers()
216        {
217                if (trackers_.empty())
218                {
219                        std::vector<lbt::announce_entry> trackers = handle_.trackers();
220                       
221                        foreach (const lbt::announce_entry& entry, trackers)
222                        {
223                                trackers_.push_back(
224                                        TrackerDetail(hal::from_utf8(entry.url), entry.tier));
225                        }
226                }               
227                return trackers_;
228        }
229       
230        void applyTrackers()
231        {
232                if (torrent_trackers_.empty())
233                        torrent_trackers_ = handle_.trackers();
234               
235                if (!trackers_.empty())
236                {
237                        std::vector<lbt::announce_entry> trackers;
238                       
239                        foreach (const TrackerDetail& tracker, trackers_)
240                        {
241                                trackers.push_back(
242                                        lbt::announce_entry(hal::to_utf8(tracker.url)));
243                                trackers.back().tier = tracker.tier;
244                        }
245                        handle_.replace_trackers(trackers);
246                }
247        }
248       
249        void setTrackers(const std::vector<TrackerDetail>& trackerDetails)
250        {
251                trackers_.clear();
252                trackers_.assign(trackerDetails.begin(), trackerDetails.end());
253               
254                applyTrackers();
255        }
256       
257        bool inSession() const { return in_session_; }
258        const wstring& saveDirectory() { return save_directory_; }
259       
260    friend class boost::serialization::access;
261    template<class Archive>
262    void serialize(Archive& ar, const unsigned int version)
263    {
264        ar & make_nvp("transferLimit", transferLimit_);
265        ar & make_nvp("connections", connections_);
266        ar & make_nvp("uploads", uploads_);
267        ar & make_nvp("filename", filename_);
268        ar & make_nvp("saveDirectory", save_directory_);
269               
270                if (version > 3) {
271                        ar & make_nvp("payloadUploaded_", payloadUploaded_);
272                        ar & make_nvp("payloadDownloaded_", payloadDownloaded_);
273                        ar & make_nvp("uploaded_", uploaded_);
274                        ar & make_nvp("downloaded_", downloaded_);             
275                } 
276                else if (version > 1)
277                {
278                        ar & make_nvp("totalUploaded", totalUploaded_);
279                        ar & make_nvp("ratio", ratio_);
280                       
281                        payloadUploaded_.reset(totalUploaded_);
282                }
283               
284                if (version > 0) {
285                        ar & make_nvp("trackerUsername", trackerUsername_);
286                        ar & make_nvp("trackerPassword", trackerPassword_);
287                }
288                if (version > 1) {
289                        ar & make_nvp("state", state_);
290                        ar & make_nvp("trackers", trackers_);
291                }
292       
293                if (version > 2) {
294                        ar & make_nvp("resolve_countries", resolve_countries_);
295                }
296    }
297       
298        void setEntryData(libtorrent::entry metadata, libtorrent::entry resumedata)
299        {               
300                metadata_ = metadata;
301                resumedata_ = resumedata;
302        }
303       
304        void applySettings()
305        {               
306                setTransferSpeed();
307                setConnectionLimit();
308                setRatio();
309                applyTrackers();
310                setResolveCountries();
311        }
312       
313        void getPeerDetails(PeerDetails& peerDetails) const
314        {
315                if (in_session_)
316                {
317                        std::vector<lbt::peer_info> peerInfo;
318                        handle_.get_peer_info(peerInfo);
319                       
320                        foreach (lbt::peer_info peer, peerInfo) 
321                        {
322                                peerDetails.push_back(peer);
323                        }       
324                }
325        }
326       
327private:
328        static libtorrent::session* the_session_;
329       
330        std::pair<float, float> transferLimit_;
331       
332        unsigned state_;
333        int connections_;
334        int uploads_;
335        bool in_session_;
336        float ratio_;
337        bool resolve_countries_;
338       
339        std::wstring filename_;
340        std::wstring save_directory_;
341        libtorrent::torrent_handle handle_;     
342       
343        libtorrent::entry metadata_;
344        libtorrent::entry resumedata_;
345       
346        std::wstring trackerUsername_; 
347        std::wstring trackerPassword_;
348       
349        mutable boost::int64_t totalUploaded_;
350        mutable boost::int64_t totalBase_;
351       
352        TransferTracker<boost::int64_t> payloadUploaded_;
353        TransferTracker<boost::int64_t> payloadDownloaded_;
354        TransferTracker<boost::int64_t> uploaded_;
355        TransferTracker<boost::int64_t> downloaded_;
356       
357        std::vector<TrackerDetail> trackers_;
358        std::vector<lbt::announce_entry> torrent_trackers_;
359};
360
361typedef std::map<std::string, TorrentInternal> TorrentMap;
362typedef std::pair<std::string, TorrentInternal> TorrentPair;
363
364void TorrentInternal::setConnectionLimit(int maxConn, int maxUpload)
365{
366        handle_.set_max_connections(maxConn);
367        handle_.set_max_uploads(maxUpload);
368
369        connections_ =  maxConn;
370        uploads_ = maxUpload;
371}
372
373void TorrentInternal::setConnectionLimit()
374{
375        handle_.set_max_connections(connections_);
376        handle_.set_max_uploads(uploads_);
377}
378
379pair<int, int> TorrentInternal::getConnectionLimit()
380{
381        return make_pair(connections_, uploads_);
382}
383
384void TorrentInternal::setTransferSpeed(float download, float upload)
385{
386        int down = (download > 0) ? static_cast<int>(download*1024) : -1;
387        handle_.set_download_limit(down);
388        int up = (upload > 0) ? static_cast<int>(upload*1024) : -1;
389        handle_.set_upload_limit(up);
390       
391        transferLimit_ = make_pair(download, upload);
392}
393
394void TorrentInternal::setTransferSpeed()
395{
396        int down = (transferLimit_.first > 0) ? static_cast<int>(transferLimit_.first*1024) : -1;
397        handle_.set_download_limit(down);
398        int up = (transferLimit_.second > 0) ? static_cast<int>(transferLimit_.second*1024) : -1;
399        handle_.set_upload_limit(up);
400}
401
402pair<float, float> TorrentInternal::getTransferSpeed()
403{
404        return transferLimit_;
405}
406
407TorrentDetail_ptr TorrentInternal::getTorrentDetail_ptr() const
408{       
409        if (inSession())
410        {
411                lbt::torrent_status tS = handle_.status();
412                wstring state;
413               
414                if (state_ == TorrentDetail::torrent_paused)
415                        state = app().res_wstr(HAL_TORRENT_PAUSED);
416                else if (state_ == TorrentDetail::torrent_stopped)
417                        state = app().res_wstr(HAL_TORRENT_STOPPED);
418                else
419                {
420                        switch (tS.state)
421                        {
422                        case lbt::torrent_status::queued_for_checking:
423                                state = app().res_wstr(HAL_TORRENT_QUEUED_CHECKING);
424                                break;
425                        case lbt::torrent_status::checking_files:
426                                state = app().res_wstr(HAL_TORRENT_CHECKING_FILES);
427                                break;
428                        case lbt::torrent_status::connecting_to_tracker:
429                                state = app().res_wstr(HAL_TORRENT_CONNECTING);
430                                break;
431                        case lbt::torrent_status::downloading_metadata:
432                                state = app().res_wstr(HAL_TORRENT_METADATA);
433                                break;
434                        case lbt::torrent_status::downloading:
435                                state = app().res_wstr(HAL_TORRENT_DOWNLOADING);
436                                break;
437                        case lbt::torrent_status::finished:
438                                state = app().res_wstr(HAL_TORRENT_FINISHED);
439                                break;
440                        case lbt::torrent_status::seeding:
441                                state = app().res_wstr(HAL_TORRENT_SEEDING);
442                                break;
443                        case lbt::torrent_status::allocating:
444                                state = app().res_wstr(HAL_TORRENT_ALLOCATING);
445                                break;
446                        }       
447                }
448               
449                boost::posix_time::time_duration td(boost::posix_time::pos_infin);
450               
451                if (tS.download_payload_rate != 0)
452                {
453                        td = boost::posix_time::seconds(       
454                                long( float(tS.total_wanted-tS.total_wanted_done) / tS.download_payload_rate ));
455                }
456               
457                totalUploaded_ += (tS.total_payload_upload - totalBase_);
458                totalBase_ = tS.total_payload_upload;
459               
460                uploaded_.update(tS.total_upload);
461                payloadUploaded_.update(tS.total_payload_upload);
462                downloaded_.update(tS.total_download);
463                payloadDownloaded_.update(tS.total_payload_download);
464
465                return TorrentDetail_ptr(new TorrentDetail(filename_, state, hal::from_utf8(tS.current_tracker), 
466                        pair<float, float>(tS.download_payload_rate, tS.upload_payload_rate),
467                        tS.progress, tS.distributed_copies, tS.total_wanted_done, tS.total_wanted, uploaded_, payloadUploaded_,
468                        downloaded_, payloadDownloaded_, tS.num_peers, tS.num_seeds, ratio_, td, tS.next_announce));
469        }
470        else
471        {
472                return TorrentDetail_ptr(new TorrentDetail(filename_, L"Not in Session", L"No tracker"));
473        }
474}
475
476} //namespace hal
Note: See TracBrowser for help on using the repository browser.