RC->FINAL
[kdenetwork.git] / kget / transfer-plugins / bittorrent / bttransfer.cpp
blob981e829fd6ef5f1dd0c379f9f0ca5bcf0e36bb0f
1 /* This file is part of the KDE project
3 Copyright (C) 2007 Lukas Appelhans <l.appelhans@gmx.de>
4 Copyright (C) 2007 Joris Guisson <joris.guisson@gmail.com>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
12 #include "bttransfer.h"
13 #include "bittorrentsettings.h"
15 #include "core/kget.h"
17 #include <torrent/torrent.h>
18 #include <peer/peermanager.h>
19 #include <util/error.h>
20 #include <torrent/globals.h>
21 #include <torrent/server.h>
22 #include <util/constants.h>
23 #include <util/functions.h>
24 #include <util/log.h>
25 #include <peer/authenticationmonitor.h>
26 #include <btdownload.h>
27 #include <btversion.h>
29 #include <KDebug>
30 #include <KLocale>
31 #include <KIconLoader>
32 #include <KStandardDirs>
33 #include <KUrl>
34 #include <KMessageBox>
36 #include <QFile>
37 #include <QDomElement>
38 #include <QFileInfo>
40 BTTransfer::BTTransfer(TransferGroup* parent, TransferFactory* factory,
41 Scheduler* scheduler, const KUrl& src, const KUrl& dest,
42 const QDomElement * e)
43 : Transfer(parent, factory, scheduler, src, dest, e),
44 torrent(0),
45 m_tmp(0),
46 m_dlLimit(BittorrentSettings::downloadLimit()),
47 m_ulLimit(BittorrentSettings::uploadLimit()),
48 m_ratio(BittorrentSettings::maxShareRatio()),
49 m_ready(false)
51 kDebug(5001);
52 if (m_source.url().isEmpty())
53 return;
55 if (e)
56 load(*e);
59 BTTransfer::~BTTransfer()
61 kDebug(5001);
62 if (torrent)
63 delete torrent;
66 /**Reimplemented functions from Transfer-Class (transfer.cpp)**/
67 bool BTTransfer::isResumable() const
69 kDebug(5001);
70 return true;
73 void BTTransfer::start()
75 kDebug(5001);
76 if (!torrent)
78 if (!m_source.isLocalFile())
80 kDebug(5001) << m_dest.path();
81 BTDownload *download = new BTDownload(m_source);
83 setStatus(Job::Stopped, i18n("Downloading Torrent-File.."), SmallIcon("document-save"));
84 setTransferChange(Tc_Status, true);
86 m_source = KStandardDirs::locateLocal("appdata", "tmp/") + m_source.fileName();
87 connect(download, SIGNAL(finishedSuccessfully(KUrl)), SLOT(init(KUrl)));
89 else
90 init();
92 else
93 startTorrent();
96 void BTTransfer::stop()
98 kDebug(5001);
99 if (m_ready)
101 stopTorrent();
105 void BTTransfer::update()
107 kDebug(5001);
109 if (torrent)
111 QStringList files;
112 if (torrent->hasMissingFiles(files))
114 kDebug(5001) << "Recreate Missing Files";
115 torrent->recreateMissingFiles();
117 updateTorrent();
119 else
120 timer.stop();
123 void BTTransfer::load(const QDomElement &e)
125 kDebug(5001);
126 m_source = KUrl(e.attribute("Source"));
127 m_dest = KUrl(e.attribute("Dest"));
129 m_totalSize = e.attribute("TotalSize").toULongLong();
130 m_processedSize = e.attribute("ProcessedSize").toULongLong();
132 if( m_totalSize != 0)
133 m_percent = (int)((100.0 * m_processedSize) / m_totalSize);
134 else
135 m_percent = 0;
137 m_ulLimit = e.attribute("Upload-Limit").toInt();
138 m_dlLimit = e.attribute("Download-Limit").toInt();
140 if((m_totalSize == m_processedSize) && (m_totalSize != 0))
142 setStatus(Job::Finished, i18n("Finished"), SmallIcon("dialog-ok"));
143 // "ok" icon should probably be "dialog-success", but we don't have that icon in KDE 4.0
145 else
147 setStatus(status(), i18n("Stopped"), SmallIcon("process-stop"));
151 void BTTransfer::save(const QDomElement &element)
153 kDebug(5001);
155 QDomElement e = element;
157 Transfer::save(e);
159 e.setAttribute("Upload-Limit", ulLimit());
160 e.setAttribute("Download-Limit", dlLimit());
163 /**Public functions of BTTransfer**/
165 void BTTransfer::setPort(int port)
167 kDebug(5001);
168 bt::Globals::instance().getServer().changePort(port);
171 void BTTransfer::setTrafficLimits(int ulLimit, int dlLimit)
173 kDebug(5001);
174 if (!torrent)
175 return;
177 torrent->setTrafficLimits(ulLimit * 1000, dlLimit * 1000);
178 m_dlLimit = dlLimit;
179 m_ulLimit = ulLimit;
182 void BTTransfer::setMaxShareRatio(float ratio)
184 if (m_ratio != ratio)
185 m_ratio = ratio;
187 if (m_ratio != 0)
188 torrent->setMaxShareRatio(m_ratio);
191 void BTTransfer::addTracker(QString url)
193 kDebug(5001);
194 if(torrent->getStats().priv_torrent)
196 KMessageBox::sorry(0, i18n("Cannot add a tracker to a private torrent."));
197 return;
200 if(!KUrl(url).isValid())
202 KMessageBox::error(0, i18n("Malformed URL."));
203 return;
206 torrent->getTrackersList()->addTracker(url,true);
209 /**Private functions**/
211 void BTTransfer::startTorrent()
213 if (m_ready)
215 kDebug(5001) << "Going to download that stuff :-0";
216 setTrafficLimits(m_ulLimit, m_dlLimit);//Set traffic-limits before starting
217 kDebug(5001) << "Here we are";
218 torrent->start();
219 kDebug(5001) << "Got started??";
220 timer.start(250);
221 setStatus(Job::Running, i18n("Downloading.."), SmallIcon("media-playback-start"));
222 kDebug(5001) << "Jepp, it does";
223 m_totalSize = totalSize();
224 setTransferChange(Tc_Status | Tc_TrackersList | Tc_TotalSize, true);
225 kDebug(5001) << "Completely";
229 void BTTransfer::stopTorrent()
231 torrent->stop(true);
232 m_speed = 0;
233 timer.stop();
234 setStatus(Job::Stopped, i18n("Stopped"), SmallIcon("process-stop"));
235 setTransferChange(Tc_Status, true);
238 void BTTransfer::updateTorrent()
240 kDebug(5001) << "Update torrent";
241 bt::UpdateCurrentTime();
242 bt::AuthenticationMonitor::instance().update();
243 kDebug(5001) << "Ignore this ;)";
244 torrent->update();
245 kDebug(5001) << "Done";
246 m_speed = dlRate();
247 m_percent = percent();
248 m_processedSize = processedSize();
250 setTransferChange(Tc_ProcessedSize | Tc_Speed | Tc_Percent, true);
253 void BTTransfer::init(KUrl src)
255 kDebug(5001);
256 if (src != m_source && !src.isEmpty())
257 m_source = src;
259 setStatus(Job::Running, i18n("Analizing torrent.."), SmallIcon("document-preview")); // jpetso says: you should probably use the "process-working" icon here (from the animations category), but that's a multi-frame PNG so it's hard for me to test
260 setTransferChange(Tc_Status, true);
262 bt::InitLog(KStandardDirs::locateLocal("appdata", "torrentlog.log"));//initialize the torrent-log
264 bt::SetClientInfo("KGet",2,0,0,bt::NORMAL,"KG");//Set client info to KGet, WARNING: Pls change this for every release
266 bt::Uint16 i = 0;
269 kDebug(5001) << "Trying to set port to" << BittorrentSettings::port() + i;
270 bt::Globals::instance().initServer(BittorrentSettings::port() + i);
271 i++;
272 }while (!bt::Globals::instance().getServer().isOK() && i < 10);
274 if (!bt::Globals::instance().getServer().isOK())
275 return;
279 torrent = new bt::TorrentControl();
281 if (!BittorrentSettings::tmpDir().isEmpty())
283 m_tmp = BittorrentSettings::tmpDir();
284 kDebug(5001) << "Trying to set" << m_tmp << " as tmpDir";
285 if (!QFileInfo(m_tmp).isDir())
286 m_tmp = KStandardDirs::locateLocal("appdata", "tmp/");
288 else
289 m_tmp = KStandardDirs::locateLocal("appdata", "tmp/");
291 m_ready = true;
293 torrent->init(0, m_source.url().remove("file://"), m_tmp + m_source.fileName().remove(".torrent"),
294 m_dest.directory().remove("file://"), 0);
296 if (torrent->getStats().multi_file_torrent)
297 m_dest = torrent->getStats().output_path;
298 else
299 m_dest = torrent->getDataDir() + torrent->getStats().torrent_name;
301 torrent->createFiles();
303 torrent->setPreallocateDiskSpace(BittorrentSettings::preAlloc());
305 setMaxShareRatio(m_ratio);
306 setTrafficLimits(m_ulLimit, m_dlLimit);
308 connect(torrent, SIGNAL(stoppedByError(bt::TorrentInterface*, QString)), SLOT(slotStoppedByError(bt::TorrentInterface*, QString)));
309 connect(torrent, SIGNAL(finished(bt::TorrentInterface*)), this, SLOT(slotDownloadFinished(bt::TorrentInterface* )));
310 //FIXME connect(tc,SIGNAL(corruptedDataFound( bt::TorrentInterface* )), this, SLOT(emitCorruptedData( bt::TorrentInterface* )));
312 catch (bt::Error &err)
314 kDebug(5001) << err.toString();
315 //m_ready = false;
317 startTorrent();
318 connect(&timer, SIGNAL(timeout()), SLOT(update()));
321 void BTTransfer::slotStoppedByError(bt::TorrentInterface* error, QString errormsg)
323 kDebug(5001) << errormsg;
326 void BTTransfer::slotDownloadFinished(bt::TorrentInterface* ti)
328 kDebug(5001);
329 timer.stop();
330 setStatus(Job::Finished, i18n("Finished"), SmallIcon("dialog-ok"));
331 setTransferChange(Tc_Status, true);
334 /**Property-Functions**/
335 KUrl::List BTTransfer::trackersList() const
337 kDebug(5001);
338 if (!torrent)
339 return KUrl::List();
341 const KUrl::List trackers = torrent->getTrackersList()->getTrackerURLs();
342 return trackers;
345 int BTTransfer::dlRate() const
347 kDebug(5001);
348 if (!torrent)
349 return -1;
351 return torrent->getStats().download_rate;
354 int BTTransfer::ulRate() const
356 kDebug(5001);
357 if (!torrent)
358 return -1;
360 return torrent->getStats().upload_rate;
363 float BTTransfer::totalSize() const
365 kDebug(5001);
366 if (!torrent)
367 return -1;
369 return torrent->getStats().total_bytes_to_download;
372 float BTTransfer::processedSize() const
374 kDebug(5001);
375 if (!torrent)
376 return -1;
378 return torrent->getStats().bytes_downloaded;
381 int BTTransfer::sessionBytesDownloaded() const
383 kDebug(5001);
384 if (!torrent)
385 return -1;
387 return torrent->getStats().session_bytes_downloaded;
390 int BTTransfer::sessionBytesUploaded() const
392 kDebug(5001);
393 if (!torrent)
394 return -1;
396 return torrent->getStats().session_bytes_uploaded;
399 int BTTransfer::chunksTotal() const
401 kDebug(5001);
402 if (!torrent)
403 return -1;
405 return torrent->getTorrent().getNumChunks();
408 int BTTransfer::chunksDownloaded() const
410 kDebug(5001);
411 if (!torrent)
412 return -1;
414 return torrent->downloadedChunksBitSet().numOnBits();
417 int BTTransfer::chunksExcluded() const
419 kDebug(5001);
420 if (!torrent)
421 return -1;
423 return torrent->excludedChunksBitSet().numOnBits();
426 int BTTransfer::chunksLeft() const
428 kDebug(5001);
429 if (!torrent)
430 return -1;
432 return chunksTotal() - chunksDownloaded();
435 int BTTransfer::seedsConnected() const
437 kDebug(5001);
438 if (!torrent)
439 return -1;
441 return torrent->getStats().seeders_connected_to;
444 int BTTransfer::seedsDisconnected() const
446 kDebug(5001);
447 if (!torrent)
448 return -1;
450 return torrent->getStats().seeders_total;
453 int BTTransfer::leechesConnected() const
455 kDebug(5001);
456 if (!torrent)
457 return -1;
459 return torrent->getStats().leechers_connected_to;
462 int BTTransfer::leechesDisconnected() const
464 kDebug(5001);
465 if (!torrent)
466 return -1;
468 return torrent->getStats().leechers_total;
471 int BTTransfer::elapsedTime() const
473 if (!torrent)
474 return -1;
476 kDebug(5001);
477 return torrent->getRunningTimeDL();
480 int BTTransfer::remainingTime() const
482 if (!torrent)
483 return -1;
485 kDebug(5001);
486 return torrent->getETA();
489 int BTTransfer::ulLimit() const
491 kDebug(5001);
492 if (!torrent)
493 return -1;
494 else
495 return m_ulLimit;
498 int BTTransfer::dlLimit() const
500 kDebug(5001);
501 if (!torrent)
502 return -1;
503 else
504 return m_dlLimit;
507 bt::TorrentControl * BTTransfer::torrentControl()
509 kDebug(5001);
510 return torrent;
513 int BTTransfer::percent() const
515 kDebug(5001);
516 if (!torrent)
517 return -1;
519 return ((float) chunksDownloaded() / (float) chunksTotal()) * 100;
522 bool BTTransfer::ready()
524 kDebug(5001);
525 return m_ready;
528 #include "bttransfer.moc"