2 * Copyright (C) 2005 Felix Berger <felixberger@beldesign.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "bttransfer.h"
23 #include <sigc++/bind.h>
24 #include <torrent/torrent.h>
25 #include <torrent/bencode.h>
26 #include <torrent/rate.h>
30 #include <kiconloader.h>
32 #include <QDomElement>
35 BTTransfer::BTTransfer(TransferGroup
* parent
, TransferFactory
* factory
,
36 Scheduler
* scheduler
, const KUrl
& src
, const KUrl
& dest
,
37 const QDomElement
* e
)
38 : Transfer(parent
, factory
, scheduler
, src
, dest
, e
),
39 m_chunksTotal(0), m_chunksDownloaded(0),
40 m_peersConnected(0), m_peersNotConnected(0)
42 BTThread::initialize(); //check: is this thread active always?? :-O
43 kDebug(5001) << "new bt transfer";
45 //We already know that the file is local (the check is in the Factory)
46 QFile
file(src
.path());
47 kDebug(5001) << "Opening file: " << src
.path();
49 if(file
.open(QIODevice::ReadOnly
))
51 kDebug(5001) << "***********Bittorrent file opened";
52 QByteArray data
= file
.readAll();
53 kDebug(5001) << "Stream of size: " << data
.size();
54 kDebug(5001) << "Stream of data: " << endl
<< data
.data();
55 bencodeStream
.write(data
.data(), data
.size());
61 kDebug(5001) << "***********Unable to open bittorrent file!";
62 kDebug(5001) << file
.errorString();
65 connect(&timer
, SIGNAL(timeout()), SLOT(update()));
68 BTTransfer::~BTTransfer()
73 bool BTTransfer::isResumable() const
78 int BTTransfer::chunksTotal()
80 if (download
.is_valid() && download
.is_active())
81 return download
.get_chunks_total();
86 int BTTransfer::chunksDownloaded()
88 if (download
.is_valid() && download
.is_active())
89 return download
.get_chunks_done();
94 int BTTransfer::peersConnected()
96 if (download
.is_valid() && download
.is_active())
97 return download
.get_peers_connected();
103 int BTTransfer::peersNotConnected()
105 if (download
.is_valid() && download
.is_active())
106 return download
.get_peers_not_connected();
111 void BTTransfer::start()
113 startTime
= QTime::currentTime();
114 setStatus(Job::Running
, i18n("Analizing torrent.."), SmallIcon("xmag"));
115 setTransferChange(Tc_Status
, true);
120 void BTTransfer::stop()
122 kDebug(5001) << endl
<< "bt stopped";
124 if (download
.is_valid())
127 // download.hash_save();
129 setStatus(Job::Stopped
, i18n("Stopped"), SmallIcon("process-stop"));
130 setTransferChange(Tc_Speed
| Tc_Status
, true);
136 int BTTransfer::elapsedTime() const
138 return startTime
.secsTo(QTime::currentTime());
141 int BTTransfer::remainingTime() const
143 // we should use the average rate here
145 return (rate
<= 0) ? -1 :
146 (int)((totalSize() - processedSize()) / rate
);
149 void BTTransfer::resume()
151 kDebug(5001) << endl
<< "resume dl";
152 if (!download
.is_valid())
156 download
= torrent::download_add(&bencodeStream
);
158 bencodeStream
.str(std::string());
160 download
.set_root_dir(std::string(qPrintable(dest().directory(false))));
162 if (download
.get_entry_size() == 1)
167 // trackerSucceeded = download.signal_tracker_succeded
168 // (sigc::bind(sigc::mem_fun(*this, &BTTransfer::trackerMessage),
170 // trackerFailed = download.signal_tracker_failed
171 // (sigc::mem_fun(*this, &BTTransfer::trackerMessage));
173 downloadDone
= download
.signal_download_done
174 (sigc::mem_fun(*this, &BTTransfer::downloadFinished
));
176 hashingDone
= download
.signal_hash_done
177 (sigc::mem_fun(*this, &BTTransfer::hashingFinished
));
179 catch (std::exception
& e
)
181 // line below only compiles with exceptions activated
182 // kDebug(5001) << "exception " << e.what();
185 kDebug(5001) << "still alive";
188 if(!download
.is_active())
190 if (!download
.is_open())
192 kDebug(5001) << endl
<< "second turn";
195 if (!download
.is_hash_checked())
197 download
.hash_check(false);
202 kDebug(5001) << endl
<< "third turn";
203 setStatus(status(), i18n("Connecting.."), SmallIcon("connect-creating"));
204 setTransferChange(Tc_Status
, true);
208 catch (std::exception
& e
)
210 // the line below only compiles with exceptions activated
211 // kDebug(5001) << "Resume exception " << e.what();
213 timer
.start(1 * 1000);
218 void BTTransfer::remove()
220 kDebug(5001) << endl
<< "bt removed";
222 if (download
.is_valid() && download
.is_active())
226 torrent::download_remove(download
.get_hash());
230 void BTTransfer::trackerMessage(std::string msg
)
232 kDebug(5001) << "trackerMessage";
233 kDebug(5001) << msg
.c_str();
236 void BTTransfer::downloadFinished()
238 kDebug(5001) << "bt transfer done ";
239 setStatus(Job::Finished
, i18n("Finished"), SmallIcon("ok"));
240 setTransferChange(Tc_Status
, true);
243 void BTTransfer::hashingFinished()
245 kDebug(5001) << "hashing finished ";
247 setTransferChange(Tc_Status
, true);
251 void BTTransfer::update()
253 kDebug(5001) << "update";
254 if (!download
.is_valid() || !download
.is_active())
256 kDebug(5001) << "timer running on invalid or inactive download";
261 // kDebug(5001) << "dl name " << download.get_name().c_str();
262 // kDebug(5001) << "processedSize " << download.get_bytes_done();
263 // kDebug(5001) << "rate down " << download.get_rate_down();
264 // kDebug(5001) << "rate up " << download.get_rate_up();
265 // kDebug(5001) << "bytes up " << download.get_bytes_up();
266 // kDebug(5001) << "bytes down " << download.get_bytes_down();
267 // kDebug(5001) << "chunk size " << download.get_chunks_size();
268 // kDebug(5001) << "chunks done " << download.get_chunks_done();
269 // kDebug(5001) << "chunks total " << download.get_chunks_total();
270 // kDebug(5001) << "peers conn " << download.get_peers_connected();
271 // kDebug(5001) << "handshakes " << torrent::get(torrent::HANDSHAKES_TOTAL);
274 m_totalSize
= download
.get_bytes_total();
275 m_processedSize
= download
.get_bytes_done();
276 m_speed
= download
.get_read_rate().rate();
279 //Make sure we are really downloading the torrent before setting the status
280 //text to "Downloading.."
282 (statusText() != i18n("Downloading..")) &&
283 (status() != Job::Finished
) )
285 setStatus(status(), i18n("Downloading.."), SmallIcon("media-playback-start"));
286 setTransferChange(Tc_Status
);
291 m_percent
= (int)((100.0 * m_processedSize
) / m_totalSize
);
292 setTransferChange(Tc_Percent
);
295 if (m_chunksTotal
!= chunksTotal())
297 m_chunksTotal
= chunksTotal();
298 setTransferChange(Tc_ChunksTotal
);
301 if (m_chunksDownloaded
!= chunksDownloaded())
303 m_chunksDownloaded
= chunksDownloaded();
304 setTransferChange(Tc_ChunksDownloaded
);
307 if (m_peersConnected
!= peersConnected())
309 m_peersConnected
= peersConnected();
310 setTransferChange(Tc_PeersConnected
);
313 if (m_peersNotConnected
!= peersNotConnected())
315 m_peersNotConnected
= peersNotConnected();
316 setTransferChange(Tc_PeersNotConnected
);
319 setTransferChange(Tc_ProcessedSize
| Tc_Speed
| Tc_TotalSize
, true);
322 void BTTransfer::save(QDomElement e
) // krazy:exclude=passbyvalue
326 if (download
.is_valid() && !download
.is_active())
328 QDomDocument
doc(e
.ownerDocument());
329 QDomElement
bencode(doc
.createElement("bencode"));
330 e
.appendChild(bencode
);
332 s
<< download
.get_bencode();
333 bencode
.appendChild(doc
.createTextNode(s
.str().c_str()));
337 void BTTransfer::load(const QDomElement
&e
)
343 QDomElement
first(e
.firstChild().toElement());
344 if (!first
.isNull() && (first
.tagName() == "bencode") )
346 bencodeStream
<< qPrintable(first
.text());
351 #include "bttransfer.moc"