File indexing completed on 2024-04-21 04:57:12
0001 /* This file is part of the KDE project 0002 0003 Copyright (C) 2008 Lukas Appelhans <l.appelhans@gmx.de> 0004 0005 This program is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 */ 0010 0011 #include "btdatasource.h" 0012 #include "bittorrentsettings.h" 0013 #include "btcache.h" 0014 #include "btchunkselector.h" 0015 #include "core/download.h" 0016 #include <QStandardPaths> 0017 #include <btversion.h> 0018 #include <peer/authenticationmonitor.h> 0019 #include <torrent/globals.h> 0020 #include <torrent/server.h> 0021 #include <torrent/torrentcontrol.h> 0022 #include <util/bitset.h> 0023 #include <util/error.h> 0024 #include <util/functions.h> 0025 #include <util/log.h> 0026 0027 using namespace bt; 0028 0029 BTDataSource::BTDataSource(const QUrl &srcUrl, QObject *parent) 0030 : TransferDataSource(srcUrl, parent) 0031 , m_offset(0) 0032 , m_bytes(0) 0033 , m_torrentSource(QUrl()) 0034 { 0035 // make sure that the DataLocation directory exists (earlier this used to be handled by KStandardDirs) 0036 if (!QFileInfo::exists(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))) { 0037 QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); 0038 } 0039 0040 bt::InitLog(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/torrentlog.log")); // initialize the torrent-log 0041 0042 bt::SetClientInfo("KGet", 2, 1, 0, bt::NORMAL, "KG"); // Set client info to KGet, WARNING: Pls change this for every release 0043 0044 bt::Uint16 i = 0; 0045 do { 0046 qCDebug(KGET_DEBUG) << "Trying to set port to" << BittorrentSettings::port() + i; 0047 bt::Globals::instance().initServer(BittorrentSettings::port() + i); 0048 i++; 0049 } while (!bt::Globals::instance().getServer().isOK() && i < 10); 0050 0051 if (!bt::Globals::instance().getServer().isOK()) 0052 return; 0053 tc = new TorrentControl(); 0054 csf = new BTChunkSelectorFactory(); 0055 cf = new BTCacheFactory(); 0056 connect(cf, SIGNAL(cacheAdded(BTCache *)), SLOT(cacheAdded(BTCache *))); 0057 connect(csf, SIGNAL(selectorAdded(BTChunkSelector *)), SLOT(selectorAdded(BTChunkSelector *))); 0058 tc->setChunkSelectorFactory(csf); 0059 tc->setCacheFactory(cf); 0060 connect(&timer, SIGNAL(timeout()), SLOT(update())); 0061 } 0062 0063 BTDataSource::~BTDataSource() 0064 { 0065 delete tc; 0066 delete cs; 0067 delete cf; 0068 } 0069 0070 void BTDataSource::cacheAdded(BTCache *cache) 0071 { 0072 connect(cache, SIGNAL(dataArrived(KIO::fileoffset_t, QByteArray)), SLOT(getData(KIO::fileoffset_t, QByteArray))); 0073 } 0074 0075 void BTDataSource::selectorAdded(BTChunkSelector *selector) 0076 { 0077 cs = selector; 0078 } 0079 0080 void BTDataSource::start() 0081 { 0082 if (m_torrentSource.isEmpty()) { 0083 QString tmpDirName = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/tmp/"); 0084 // make sure that the /tmp directory exists (earlier this used to be handled by KStandardDirs) 0085 if (!QFileInfo::exists(tmpDirName)) { 0086 QDir().mkpath(tmpDirName); 0087 } 0088 Download *download = new Download(m_source, tmpDirName + m_source.fileName()); 0089 connect(download, SIGNAL(finishedSuccessfully(QUrl, QByteArray)), SLOT(init(QUrl, QByteArray))); 0090 } else { 0091 cs->excludeAll(); 0092 const BitSet &bits = tc->availableChunksBitSet(); 0093 bool av = true; 0094 Uint32 firstChunk = m_offset / tc->getStats().chunk_size; 0095 Uint32 lastChunk = ((m_offset + m_bytes) / tc->getStats().chunk_size) + 1; // The +1 is only a workaround for rounding up, but I dunno how to do it ;) 0096 for (int i = firstChunk * tc->getStats().chunk_size * 8; i <= lastChunk * tc->getStats().chunk_size * 8; i++) { 0097 if (!bits.get(i)) { 0098 emit broken(); 0099 av = false; 0100 continue; 0101 } 0102 } 0103 if (av) { 0104 cs->reincluded(firstChunk, lastChunk); 0105 tc->start(); 0106 timer.start(250); 0107 } 0108 } 0109 } 0110 0111 void BTDataSource::stop() 0112 { 0113 tc->stop(true); 0114 timer.stop(); 0115 } 0116 0117 void BTDataSource::update() 0118 { 0119 bt::UpdateCurrentTime(); 0120 bt::AuthenticationMonitor::instance().update(); 0121 tc->update(); 0122 } 0123 0124 void BTDataSource::init(const QUrl &torrentSource, const QByteArray &data) 0125 { 0126 Q_UNUSED(data) 0127 m_torrentSource = torrentSource; 0128 try { 0129 tc->init(0, m_torrentSource.url(), QString(), QString(), 0); 0130 } catch (bt::Error &err) { 0131 qCDebug(KGET_DEBUG) << err.toString(); 0132 // m_ready = false; 0133 } 0134 start(); 0135 } 0136 0137 void BTDataSource::addSegment(const KIO::fileoffset_t offset, const KIO::fileoffset_t bytes, int segmentNum) 0138 { 0139 qCDebug(KGET_DEBUG); 0140 0141 if (offset < m_offset) { 0142 m_offset = offset; 0143 if (m_bytes < bytes + m_offset - offset) { 0144 m_bytes = bytes + m_offset - offset; 0145 } 0146 } 0147 if (offset > m_offset && m_bytes < bytes + m_offset - offset) { 0148 m_bytes = bytes + m_offset - offset; 0149 } 0150 if (offset == m_offset && m_bytes < bytes) { 0151 m_bytes = bytes; 0152 } 0153 } 0154 0155 void BTDataSource::getData(const KIO::fileoffset_t &off, const QByteArray &dataArray) 0156 { 0157 QByteArray splittedData; 0158 if (off < m_offset) 0159 splittedData = dataArray.right(dataArray.size() - (m_offset - off)); 0160 else if (m_offset + m_bytes < off + dataArray.size()) 0161 splittedData = dataArray.left((off + dataArray.size()) - (m_offset + m_bytes)); 0162 else 0163 splittedData = dataArray; 0164 0165 emit data(off, splittedData); 0166 0167 if (m_offset + m_bytes == off + dataArray.size()) 0168 emit finished(); 0169 } 0170 0171 #include "moc_btdatasource.cpp"