• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

kget

bttransfer.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002 
00003    Copyright (C) 2007-2008 Lukas Appelhans <l.appelhans@gmx.de>
00004    Copyright (C) 2007 Joris Guisson   <joris.guisson@gmail.com>
00005 
00006    This program is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 */
00011 
00012 #include "bttransfer.h"
00013 #include "bittorrentsettings.h"
00014 #include "bttransferhandler.h"
00015 #include "btchunkselector.h"
00016 #include "advanceddetails/monitor.h"
00017 #include "core/kget.h"
00018 #include "core/download.h"
00019 
00020 #include <torrent/torrent.h>
00021 #include <peer/peermanager.h>
00022 #include <util/error.h>
00023 #include <torrent/globals.h>
00024 #include <torrent/server.h>
00025 #include <util/constants.h>
00026 #include <util/functions.h>
00027 #include <util/log.h>
00028 #include <peer/authenticationmonitor.h>
00029 #include <btversion.h>
00030 
00031 #include <KDebug>
00032 #include <KLocale>
00033 #include <KIconLoader>
00034 #include <KStandardDirs>
00035 #include <KUrl>
00036 #include <KMessageBox>
00037 
00038 #include <QFile>
00039 #include <QDomElement>
00040 #include <QFileInfo>
00041 #include <QDir>
00042 
00043 BTTransfer::BTTransfer(TransferGroup* parent, TransferFactory* factory,
00044                Scheduler* scheduler, const KUrl& src, const KUrl& dest,
00045                const QDomElement * e)
00046   : Transfer(parent, factory, scheduler, src, dest, e),
00047     torrent(0),
00048     m_tmp(KStandardDirs::locateLocal("appdata", "tmp/")),
00049     m_ready(false),
00050     m_downloadFinished(false)
00051 {
00052     if (m_source.url().isEmpty())
00053         return;
00054 }
00055 
00056 BTTransfer::~BTTransfer()
00057 {
00058     if(torrent)
00059         torrent->setMonitor(0);
00060 
00061     delete torrent;
00062 }
00063 
00065 bool BTTransfer::isResumable() const
00066 {
00067     return true;
00068 }
00069 
00070 void BTTransfer::start()
00071 {
00072     if (!torrent)
00073     {
00074         if (!m_source.isLocalFile())
00075         {
00076             kDebug(5001) << m_dest.path();
00077             Download *download = new Download(m_source, KStandardDirs::locateLocal("appdata", "tmp/") + m_source.fileName());
00078 
00079             setStatus(Job::Stopped, i18n("Downloading Torrent-File.."), SmallIcon("document-save"));
00080             setTransferChange(Tc_Status, true);
00081 
00082             //m_source = KStandardDirs::locateLocal("appdata", "tmp/") + m_source.fileName();
00083             connect(download, SIGNAL(finishedSuccessfully(KUrl, QByteArray)), SLOT(init(KUrl)));
00084         }
00085         else
00086             init();
00087     }
00088     else
00089         startTorrent();
00090 }
00091 
00092 void BTTransfer::stop()
00093 {
00094     if (m_ready)
00095     {
00096         stopTorrent();
00097     }
00098 }
00099 
00101 void BTTransfer::update()
00102 {
00103     if (torrent)
00104     {
00105         QStringList files;
00106         if (torrent->hasMissingFiles(files))
00107         {
00108             torrent->recreateMissingFiles();
00109         }
00110         updateTorrent();
00111     }
00112     else
00113         timer.stop();
00114 }
00115 
00116 void BTTransfer::postDeleteEvent()
00117 {
00118     QDir tmpDir(m_tmp);
00119     kDebug(5001) << m_tmp + m_source.fileName().remove(".torrent");
00120     tmpDir.rmdir(m_source.fileName().remove(".torrent") + "/dnd");
00121     tmpDir.cd(m_source.fileName().remove(".torrent"));
00122     QStringList list = tmpDir.entryList();
00123 
00124     foreach (const QString &file, list)
00125     {
00126         tmpDir.remove(file);
00127     }
00128     tmpDir.cdUp();
00129     tmpDir.rmdir(m_source.fileName().remove(".torrent"));
00130 
00131     kDebug(5001) << m_source.url();
00132     QFile torrentFile(m_source.url().remove("file://"));
00133     torrentFile.remove();
00134 }
00135 
00172 void BTTransfer::setPort(int port)
00173 {
00174     bt::Globals::instance().getServer().changePort(port);
00175 }
00176 
00177 void BTTransfer::setSpeedLimits(int ulLimit, int dlLimit)
00178 {
00179     kDebug(5001);
00180     if (!torrent)
00181         return;
00182 
00183     torrent->setTrafficLimits(ulLimit * 1000, dlLimit * 1000);
00184 }
00185 
00186 void BTTransfer::addTracker(const QString &url)
00187 {
00188     kDebug(5001);
00189     if(torrent->getStats().priv_torrent)
00190     {
00191     KMessageBox::sorry(0, i18n("Cannot add a tracker to a private torrent."));
00192     return;
00193     }
00194 
00195     if(!KUrl(url).isValid())
00196     {
00197     KMessageBox::error(0, i18n("Malformed URL."));
00198     return;
00199     }
00200 
00201     torrent->getTrackersList()->addTracker(url,true);
00202 }
00203 
00206 void BTTransfer::startTorrent()
00207 {
00208     if (m_ready)
00209     {
00210         //kDebug(5001) << "Going to download that stuff :-0";
00211         setSpeedLimits(uploadLimit(Transfer::InvisibleSpeedLimit), downloadLimit(Transfer::InvisibleSpeedLimit));//Set traffic-limits before starting
00212         torrent->setMonitor(this);
00213         torrent->start();
00214         timer.start(250);
00215         setStatus(Job::Running, i18nc("transfer state: downloading", "Downloading.."), SmallIcon("media-playback-start"));
00216         m_totalSize = torrent->getStats().total_bytes_to_download;
00217         setTransferChange(Tc_Status | Tc_TrackersList | Tc_TotalSize, true);
00218     }
00219 }
00220 
00221 void BTTransfer::stopTorrent()
00222 {
00223     torrent->stop(true);
00224     torrent->setMonitor(0);
00225     m_downloadSpeed = 0;
00226     timer.stop();
00227 
00228     if (m_downloadFinished)
00229     {
00230         setStatus(Job::Stopped, i18nc("transfer state: finished", "Finished"), SmallIcon("dialog-ok"));
00231     }
00232     else
00233         setStatus(Job::Stopped, i18nc("transfer state: stopped", "Stopped"), SmallIcon("process-stop"));
00234     setTransferChange(Tc_Status, true);
00235 }
00236 
00237 void BTTransfer::updateTorrent()
00238 {
00239     //kDebug(5001) << "Update torrent";
00240     if (chunksTotal() == chunksDownloaded())
00241         slotDownloadFinished(torrent);
00242 
00243     bt::UpdateCurrentTime();
00244     bt::AuthenticationMonitor::instance().update();
00245     torrent->update();
00246 
00247     ChangesFlags changesFlags = 0;
00248 
00249     if(m_downloadedSize != (m_downloadedSize = torrent->getStats().bytes_downloaded) )
00250         changesFlags |= Tc_DownloadedSize;
00251 
00252     if(m_uploadSpeed != torrent->getStats().upload_rate )
00253     {
00254         m_uploadSpeed = torrent->getStats().upload_rate;
00255         changesFlags |= Tc_UploadSpeed;
00256     }
00257 
00258     if(m_downloadSpeed != torrent->getStats().download_rate )
00259     {
00260         m_downloadSpeed = torrent->getStats().download_rate;
00261         changesFlags |= Tc_DownloadSpeed;
00262     }
00263 
00264     int percent = (((float) chunksDownloaded() / (float) chunksTotal()) * 100);
00265     if (m_percent != percent) {
00266         m_percent = percent;
00267         changesFlags |= Tc_Percent;
00268     }
00269 
00270     setTransferChange(changesFlags, true);
00271 }
00272 
00273 void BTTransfer::init(const KUrl &src, const QByteArray &data)
00274 {
00275     Q_UNUSED(data);
00276     kDebug(5001);
00277     if (src != m_source && !src.isEmpty())
00278         m_source = src;
00279 
00280     QFile file(m_source.url().remove("file://"));
00281     if (!file.exists())
00282         return;
00283 
00284     setStatus(Job::Running, i18n("Analyzing 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
00285     setTransferChange(Tc_Status, true);
00286 
00287     bt::InitLog(KStandardDirs::locateLocal("appdata", "torrentlog.log"));//initialize the torrent-log
00288 
00289     bt::SetClientInfo("KGet",2,1,0,bt::NORMAL,"KG");//Set client info to KGet, WARNING: Pls change this for every release
00290 
00291     bt::Uint16 i = 0;
00292     do
00293     {
00294         bt::Globals::instance().initServer(BittorrentSettings::port() + i);
00295         i++;
00296     }while (!bt::Globals::instance().getServer().isOK() && i < 10);
00297 
00298     if (!bt::Globals::instance().getServer().isOK())
00299         return;
00300 
00301     try
00302     {
00303         torrent = new bt::TorrentControl();
00304 
00305         if (!BittorrentSettings::tmpDir().isEmpty())
00306         {
00307             if (QFileInfo(BittorrentSettings::tmpDir()).isDir())
00308                 m_tmp = BittorrentSettings::tmpDir();
00309         }
00310 
00311         m_ready = true;
00312 
00313         torrent->init(0, m_source.url().remove("file://"), m_tmp + m_source.fileName().remove(".torrent"),
00314                                                              m_dest.directory().remove("file://"), 0);
00315 
00316         if (torrent->getStats().multi_file_torrent)
00317             m_dest = torrent->getStats().output_path;
00318         else
00319             m_dest = torrent->getDataDir() + torrent->getStats().torrent_name;
00320 
00321         torrent->createFiles();
00322 
00323         torrent->setPreallocateDiskSpace(BittorrentSettings::preAlloc());
00324 
00325         setMaximumShareRatio(BittorrentSettings::maxShareRatio());
00326 
00327         connect(torrent, SIGNAL(stoppedByError(bt::TorrentInterface*, QString)), SLOT(slotStoppedByError(bt::TorrentInterface*, QString)));
00328         connect(torrent, SIGNAL(finished(bt::TorrentInterface*)), this, SLOT(slotDownloadFinished(bt::TorrentInterface* )));
00329         //FIXME connect(tc,SIGNAL(corruptedDataFound( bt::TorrentInterface* )), this, SLOT(emitCorruptedData( bt::TorrentInterface* )));
00330     }
00331     catch (bt::Error &err)
00332     {
00333         kDebug(5001) << err.toString();
00334         //m_ready = false;
00335     }
00336     startTorrent();
00337     connect(&timer, SIGNAL(timeout()), SLOT(update()));
00338 }
00339 
00340 void BTTransfer::slotStoppedByError(const bt::TorrentInterface* &error, const QString &errormsg)
00341 {
00342     Q_UNUSED(error);
00343     kDebug(5001) << errormsg;
00344 }
00345 
00346 void BTTransfer::slotDownloadFinished(bt::TorrentInterface* ti)
00347 {
00348     kDebug(5001) << "Start seeding *********************************************************************";
00349     Q_UNUSED(ti);
00350     m_downloadFinished = true;
00351     timer.stop();
00352     setStatus(Job::Running, i18nc("Transfer status: seeding", "Seeding.."), SmallIcon("media-playback-start"));
00353     setTransferChange(Tc_Status, true);
00354 }
00355 
00357 KUrl::List BTTransfer::trackersList() const
00358 {
00359     if (!torrent)
00360         return KUrl::List();
00361 
00362     const KUrl::List trackers = torrent->getTrackersList()->getTrackerURLs();
00363     return trackers;
00364 }
00365 
00366 int BTTransfer::sessionBytesDownloaded() const
00367 {
00368     if (!torrent)
00369         return -1;
00370 
00371     return torrent->getStats().session_bytes_downloaded;
00372 }
00373 
00374 int BTTransfer::sessionBytesUploaded() const
00375 {
00376     if (!torrent)
00377         return -1;
00378 
00379     return torrent->getStats().session_bytes_uploaded;
00380 }
00381 
00382 int BTTransfer::chunksTotal() const
00383 {
00384     if (!torrent)
00385         return -1;
00386 
00387     return torrent->getTorrent().getNumChunks();
00388 }
00389 
00390 int BTTransfer::chunksDownloaded() const
00391 {
00392     if (!torrent)
00393         return -1;
00394 
00395     return torrent->downloadedChunksBitSet().numOnBits();
00396 }
00397 
00398 int BTTransfer::chunksExcluded() const
00399 {
00400     if (!torrent)
00401         return -1;
00402 
00403     return torrent->excludedChunksBitSet().numOnBits();
00404 }
00405 
00406 int BTTransfer::chunksLeft() const
00407 {
00408     if (!torrent)
00409         return -1;
00410 
00411     return chunksTotal() - chunksDownloaded();
00412 }
00413 
00414 int BTTransfer::seedsConnected() const
00415 {
00416     if (!torrent)
00417         return -1;
00418 
00419     return torrent->getStats().seeders_connected_to;
00420 }
00421 
00422 int BTTransfer::seedsDisconnected() const
00423 {
00424     if (!torrent)
00425         return -1;
00426 
00427     return torrent->getStats().seeders_total;
00428 }
00429 
00430 int BTTransfer::leechesConnected() const
00431 {
00432     if (!torrent)
00433         return -1;
00434 
00435     return torrent->getStats().leechers_connected_to;
00436 }
00437 
00438 int BTTransfer::leechesDisconnected() const
00439 {
00440     if (!torrent)
00441         return -1;
00442 
00443     return torrent->getStats().leechers_total;
00444 }
00445 
00446 int BTTransfer::elapsedTime() const
00447 {
00448     if (!torrent)
00449         return -1;
00450 
00451     return torrent->getRunningTimeDL();
00452 }
00453 
00454 int BTTransfer::remainingTime() const
00455 {
00456     if (!torrent)
00457         return Transfer::remainingTime();
00458 
00459     return torrent->getETA();
00460 }
00461 
00462 bt::TorrentControl * BTTransfer::torrentControl()
00463 {
00464     return torrent;
00465 }
00466 
00467 bool BTTransfer::ready()
00468 {
00469     return m_ready;
00470 }
00471 
00472 void BTTransfer::downloadRemoved(bt::ChunkDownloadInterface* cd)
00473 {
00474     if (static_cast<BTTransferHandler*>(handler())->torrentMonitor())
00475         static_cast<BTTransferHandler*>(handler())->torrentMonitor()->downloadRemoved(cd);
00476 
00477     setTransferChange(Tc_ChunksTotal | Tc_ChunksDownloaded | Tc_ChunksExcluded | Tc_ChunksLeft, true);
00478 }
00479 
00480 void BTTransfer::downloadStarted(bt::ChunkDownloadInterface* cd)
00481 {
00482     if (static_cast<BTTransferHandler*>(handler())->torrentMonitor())
00483         static_cast<BTTransferHandler*>(handler())->torrentMonitor()->downloadStarted(cd);
00484 
00485     setTransferChange(Tc_ChunksTotal | Tc_ChunksDownloaded | Tc_ChunksExcluded | Tc_ChunksLeft, true);
00486 }
00487 
00488 void BTTransfer::peerAdded(bt::PeerInterface* peer)
00489 {
00490     if (static_cast<BTTransferHandler*>(handler())->torrentMonitor())
00491         static_cast<BTTransferHandler*>(handler())->torrentMonitor()->peerAdded(peer);
00492 
00493     setTransferChange(Tc_SeedsConnected | Tc_SeedsDisconnected | Tc_LeechesConnected | Tc_LeechesDisconnected, true);
00494 }
00495 
00496 void BTTransfer::peerRemoved(bt::PeerInterface* peer)
00497 {
00498     if (static_cast<BTTransferHandler*>(handler())->torrentMonitor())
00499         static_cast<BTTransferHandler*>(handler())->torrentMonitor()->peerRemoved(peer);
00500 
00501     setTransferChange(Tc_SeedsConnected | Tc_SeedsDisconnected | Tc_LeechesConnected | Tc_LeechesDisconnected, true);
00502 }
00503 
00504 void BTTransfer::stopped()
00505 {
00506     if (static_cast<BTTransferHandler*>(handler())->torrentMonitor())
00507         static_cast<BTTransferHandler*>(handler())->torrentMonitor()->stopped();
00508 }
00509 
00510 void BTTransfer::destroyed()
00511 {
00512     if (static_cast<BTTransferHandler*>(handler())->torrentMonitor())
00513         static_cast<BTTransferHandler*>(handler())->torrentMonitor()->destroyed();
00514 }
00515 
00516 #include "bttransfer.moc"

kget

Skip menu "kget"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal