[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: extragear/network/ktorrent
From: Joris Guisson <joris.guisson () gmail ! com>
Date: 2006-09-09 17:04:54
Message-ID: 1157821494.250914.12847.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 582527 by guisson:
Added HTTP tracker scraping
M +2 -3 apps/ktorrent/ktorrent.cpp
M +7 -7 ktorrent.kdevelop
M +8 -4 libktorrent/torrent/bdecoder.cpp
M +40 -8 libktorrent/torrent/bnode.cpp
M +17 -4 libktorrent/torrent/bnode.h
M +106 -32 libktorrent/torrent/httptracker.cpp
M +5 -4 libktorrent/torrent/httptracker.h
M +1 -1 libktorrent/torrent/peersourcemanager.cpp
M +6 -0 libktorrent/torrent/tracker.h
M +7 -3 libktorrent/torrent/udptracker.cpp
M +1 -1 libktorrent/torrent/udptracker.h
M +7 -0 libktorrent/util/sha1hash.cpp
M +5 -0 libktorrent/util/sha1hash.h
M +1 -1 plugins/upnp/upnpmcastsocket.cpp
--- trunk/extragear/network/ktorrent/apps/ktorrent/ktorrent.cpp #582526:582527
@@ -101,8 +101,7 @@
hide();
setAutoSaveSettings();
setToolviewStyle(KMdi::TextAndIcon);
-
- bool debug = bt::Globals::instance().isDebugModeSet();
+
KIconLoader* iload = KGlobal::iconLoader();
m_view = new KTorrentView(0);
@@ -856,7 +855,7 @@
}
}
-void KTorrent::currentTabChanged(QWidget* w)
+void KTorrent::currentTabChanged(QWidget* )
{
KMdiChildView* child = activeWindow();
if (!child)
--- trunk/extragear/network/ktorrent/ktorrent.kdevelop #582526:582527
@@ -14,7 +14,7 @@
</keywords>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
- <description></description>
+ <description/>
<ignoreparts/>
<versioncontrol>kdevsubversion</versioncontrol>
</general>
@@ -150,14 +150,14 @@
<general>
<dbgshell>libtool</dbgshell>
<programargs>--nofork --debug</programargs>
- <gdbpath></gdbpath>
+ <gdbpath/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
<runappinappdirectory>true</runappinappdirectory>
- <configGdbScript></configGdbScript>
- <runShellScript></runShellScript>
- <runGdbScript></runGdbScript>
+ <configGdbScript/>
+ <runShellScript/>
+ <runGdbScript/>
</general>
<display>
<staticmembers>false</staticmembers>
@@ -232,7 +232,7 @@
<headerCompletionDelay>250</headerCompletionDelay>
</codecompletion>
<creategettersetter>
- <prefixGet></prefixGet>
+ <prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
@@ -245,7 +245,7 @@
<qt>
<used>true</used>
<version>3</version>
- <root></root>
+ <root/>
</qt>
</kdevcppsupport>
<kdevvisualadvance>
--- trunk/extragear/network/ktorrent/libktorrent/torrent/bdecoder.cpp #582526:582527
@@ -75,13 +75,17 @@
while (data[pos] != 'e' && pos < data.size())
{
if (verbose) Out() << "Key : " << endl;
- BValueNode* k = dynamic_cast<BValueNode*>(decode());
+ BNode* kn = decode();
+ BValueNode* k = dynamic_cast<BValueNode*>(kn);
if (!k || k->data().getType() != Value::STRING)
+ {
+ delete kn;
throw Error(i18n("Decode error"));
+ }
- QString key = k->data().toString();
- delete k;
-
+ QByteArray key = k->data().toByteArray();
+ delete kn;
+
BNode* data = decode();
curr->insert(key,data);
}
--- trunk/extragear/network/ktorrent/libktorrent/torrent/bnode.cpp #582526:582527
@@ -52,22 +52,52 @@
BDictNode::BDictNode(Uint32 off) : BNode(DICT,off)
{
- children.setAutoDelete(true);
}
BDictNode::~BDictNode()
{
+ QValueList<DictEntry>::iterator i = children.begin();
+ while (i != children.end())
+ {
+ DictEntry & e = *i;
+ delete e.node;
+ i++;
+ }
}
- void BDictNode::insert(const QString & key,BNode* node)
+ void BDictNode::insert(const QByteArray & key,BNode* node)
{
- children.insert(key,node);
+ DictEntry entry;
+ entry.key = key;
+ entry.node = node;
+ children.append(entry);
}
BNode* BDictNode::getData(const QString & key)
{
- return children.find(key);
+ QValueList<DictEntry>::iterator i = children.begin();
+ while (i != children.end())
+ {
+ DictEntry & e = *i;
+ if (QString(e.key) == key)
+ return e.node;
+ i++;
+ }
+ return 0;
}
+
+ BDictNode* BDictNode::getDict(const QByteArray & key)
+ {
+ QValueList<DictEntry>::iterator i = children.begin();
+ while (i != children.end())
+ {
+ DictEntry & e = *i;
+ if (e.key == key)
+ return dynamic_cast<BDictNode*>(e.node);
+ i++;
+ }
+ return 0;
+ }
BListNode* BDictNode::getList(const QString & key)
{
@@ -90,11 +120,13 @@
void BDictNode::printDebugInfo()
{
Out() << "DICT" << endl;
- QDictIterator<BNode> it( children );
- for( ; it.current(); ++it )
+ QValueList<DictEntry>::iterator i = children.begin();
+ while (i != children.end())
{
- Out() << it.currentKey() << ": " << endl;
- it.current()->printDebugInfo();
+ DictEntry & e = *i;
+ Out() << QString(e.key) << ": " << endl;
+ e.node->printDebugInfo();
+ i++;
}
Out() << "END" << endl;
}
--- trunk/extragear/network/ktorrent/libktorrent/torrent/bnode.h #582526:582527
@@ -21,10 +21,11 @@
#define BTBNODE_H
#include <qptrlist.h>
-#include <qdict.h>
+#include <qvaluelist.h>
+#include <util/constants.h>
#include "value.h"
-#include <util/constants.h>
+
namespace bt
{
class BListNode;
@@ -96,7 +97,12 @@
*/
class BDictNode : public BNode
{
- QDict<BNode> children;
+ struct DictEntry
+ {
+ QByteArray key;
+ BNode* node;
+ };
+ QValueList<DictEntry> children;
public:
BDictNode(Uint32 off);
virtual ~BDictNode();
@@ -106,7 +112,7 @@
* @param key The key
* @param node The node
*/
- void insert(const QString & key,BNode* node);
+ void insert(const QByteArray & key,BNode* node);
/**
* Get a BNode.
@@ -128,6 +134,13 @@
* @return The node or 0 if there is no dict node with has key @a key
*/
BDictNode* getDict(const QString & key);
+
+ /**
+ * Get a BDictNode.
+ * @param key The key
+ * @return The node or 0 if there is no dict node with has key @a key
+ */
+ BDictNode* getDict(const QByteArray & key);
/**
* Get a BValueNode.
--- trunk/extragear/network/ktorrent/libktorrent/torrent/httptracker.cpp #582526:582527
@@ -44,7 +44,7 @@
HTTPTracker::HTTPTracker(const KURL & url,kt::TorrentInterface* tor,const PeerID & id)
: Tracker(url,tor,id)
{
- active_job = 0;
+ active_job = active_scrape_job = 0;
connect(&timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
interval = 5 * 60 * 1000; // default interval 5 minutes
@@ -54,7 +54,8 @@
HTTPTracker::~HTTPTracker()
- {}
+ {
+ }
void HTTPTracker::start()
{
@@ -96,11 +97,94 @@
timer.start(30000);
}
+ void HTTPTracker::scrape()
+ {
+ if (!url.fileName(false).startsWith("announce"))
+ {
+ Out(SYS_TRK|LOG_NOTICE) << "Tracker " << url << " does not support scraping" << endl;
+ return;
+ }
+
+ KURL scrape_url = url;
+ scrape_url.setFileName(url.fileName(false).replace("announce","scrape"));
+
+ QString epq = scrape_url.encodedPathAndQuery();
+ const SHA1Hash & info_hash = tor->getInfoHash();
+ if (scrape_url.queryItems().count() > 0)
+ epq += "&infohash=" + info_hash.toURLString();
+ else
+ epq += "?infohash=" + info_hash.toURLString();
+ scrape_url.setEncodedPathAndQuery(epq);
+
+ Out(SYS_TRK|LOG_NOTICE) << "Doing scrape request to url : " << scrape_url.prettyURL() << endl;
+ KIO::MetaData md;
+ md["UserAgent"] = "ktorrent/" VERSION;
+ md["SendLanguageSettings"] = "false";
+ md["Cookies"] = "none";
+
+ KIO::StoredTransferJob* j = KIO::storedGet(scrape_url,false,false);
+ // set the meta data
+ j->setMetaData(md);
+
+ connect(j,SIGNAL(result(KIO::Job* )),this,SLOT(onScrapeResult( KIO::Job* )));
+ active_scrape_job = j;
+ }
+
+ void HTTPTracker::onScrapeResult(KIO::Job* j)
+ {
+ if (j->error())
+ {
+ Out(SYS_TRK|LOG_IMPORTANT) << "Scrape failed : " << j->errorString() << endl;
+ return;
+ }
+
+ KIO::StoredTransferJob* st = (KIO::StoredTransferJob*)j;
+ BDecoder dec(st->data(),false,0);
+ BNode* n = 0;
+
+ try
+ {
+ n = dec.decode();
+ }
+ catch (bt::Error & err)
+ {
+ Out(SYS_TRK|LOG_IMPORTANT) << "Invalid scrape data " << err.toString() << endl;
+ return;
+ }
+
+ if (n && n->getType() == BNode::DICT)
+ {
+ BDictNode* d = (BDictNode*)n;
+ d = d->getDict("files");
+ if (d)
+ {
+ d = d->getDict(tor->getInfoHash().toByteArray());
+ if (d)
+ {
+ BValueNode* vn = d->getValue("complete");
+ if (vn && vn->data().getType() == Value::INT)
+ {
+ seeders = vn->data().toInt();
+ }
+
+
+ vn = d->getValue("incomplete");
+ if (vn && vn->data().getType() == Value::INT)
+ {
+ leechers = vn->data().toInt();
+ }
+
+ Out(SYS_TRK|LOG_DEBUG) << "Scrape : leechers = " << leechers
+ << ", seeders = " << seeders << endl;
+ }
+ }
+ }
+
+ delete n;
+ }
+
void HTTPTracker::doRequest()
{
- // clear data array
- data = QByteArray();
-
const TorrentStats & s = tor->getStats();
KURL u = url;
@@ -143,18 +227,17 @@
md["SendLanguageSettings"] = "false";
md["Cookies"] = "none";
- KIO::TransferJob* j = KIO::get(u,true,false);
+ KIO::StoredTransferJob* j = KIO::storedGet(u,false,false);
// set the meta data
j->setMetaData(md);
- connect(j,SIGNAL(result(KIO::Job* )),this,SLOT(onResult(KIO::Job* )));
- connect(j,SIGNAL(data(KIO::Job*,const QByteArray &)),
- this,SLOT(onDataRecieved(KIO::Job*, const QByteArray& )));
+ connect(j,SIGNAL(result(KIO::Job* )),this,SLOT(onAnnounceResult( KIO::Job* )));
+
active_job = j;
requestPending();
}
- bool HTTPTracker::updateData()
+ bool HTTPTracker::updateData(const QByteArray & data)
{
//#define DEBUG_PRINT_RESPONSE
#ifdef DEBUG_PRINT_RESPONSE
@@ -177,7 +260,16 @@
}
BDecoder dec(data,false,i);
- BNode* n = dec.decode();
+ BNode* n = 0;
+ try
+ {
+ n = dec.decode();
+ }
+ catch (...)
+ {
+ requestFailed(i18n("Invalid data from tracker"));
+ return false;
+ }
if (!n || n->getType() != BNode::DICT)
{
@@ -258,8 +350,7 @@
}
-
- void HTTPTracker::onResult(KIO::Job* j)
+ void HTTPTracker::onAnnounceResult(KIO::Job* j)
{
if (j != active_job)
{
@@ -285,6 +376,7 @@
else
{
timer.stop();
+ KIO::StoredTransferJob* st = (KIO::StoredTransferJob*)active_job;
failures = 0;
active_job = 0;
if (event != "stopped")
@@ -293,10 +385,9 @@
started = true;
event = QString::null;
-
try
{
- if (updateData())
+ if (updateData(st->data()))
{
peersReady(this);
requestOK();
@@ -313,24 +404,7 @@
}
}
}
-
- void HTTPTracker::onDataRecieved(KIO::Job* j,const QByteArray & ba)
- {
- if (j != active_job)
- {
- return;
- }
- if (ba.size() > 0)
- {
- Uint32 old_size = data.size();
- data.resize(data.size() + ba.size());
- for (Uint32 i = old_size;i < data.size();i++)
- data[i] = ba[i - old_size];
- }
-
- }
-
void HTTPTracker::onTimeout()
{
if (active_job)
--- trunk/extragear/network/ktorrent/libktorrent/torrent/httptracker.h #582526:582527
@@ -50,20 +50,21 @@
virtual void completed();
virtual void manualUpdate();
virtual Uint32 failureCount() const {return failures;}
+ virtual void scrape();
private slots:
- void onResult(KIO::Job* j);
- void onDataRecieved(KIO::Job* j,const QByteArray & ba);
+ void onAnnounceResult(KIO::Job* j);
+ void onScrapeResult(KIO::Job* j);
void onTimeout();
private:
void doRequest();
- bool updateData();
+ bool updateData(const QByteArray & data);
private:
QTimer timer;
- QByteArray data;
KIO::Job* active_job;
+ KIO::Job* active_scrape_job;
QString event;
Uint32 failures;
};
--- trunk/extragear/network/ktorrent/libktorrent/torrent/peersourcemanager.cpp #582526:582527
@@ -380,8 +380,8 @@
if (started)
{
timer.start(curr->getInterval() * 1000,true);
+ curr->scrape();
}
-
pending = false;
if (started)
statusChanged(i18n("OK"));
--- trunk/extragear/network/ktorrent/libktorrent/torrent/tracker.h #582526:582527
@@ -73,6 +73,12 @@
virtual Uint32 failureCount() const = 0;
/**
+ * Do a tracker scrape to get more accurate stats about a torrent.
+ * Does nothing if the tracker does not support this.
+ */
+ virtual void scrape() = 0;
+
+ /**
* Get the update interval in ms
* @return interval
*/
--- trunk/extragear/network/ktorrent/libktorrent/torrent/udptracker.cpp #582526:582527
@@ -162,14 +162,14 @@
if (tid != transaction_id)
return;
- Out() << "UDPTracker::error : " << error_string << endl;
+ Out(SYS_TRK|LOG_IMPORTANT) << "UDPTracker::error : " << error_string << endl;
requestFailed(error_string);
}
bool UDPTracker::doRequest()
{
- Out() << "Doing tracker request to url : " << url << endl;
+ Out(SYS_TRK|LOG_NOTICE) << "Doing tracker request to url : " << url << endl;
if (connection_id == 0)
{
n = 0;
@@ -181,6 +181,10 @@
requestPending();
return true;
}
+
+ void UDPTracker::scrape()
+ {
+ }
void UDPTracker::sendConnect()
{
@@ -194,7 +198,7 @@
void UDPTracker::sendAnnounce()
{
- // Out() << "UDPTracker::sendAnnounce()" << endl;
+ // Out(SYS_TRK|LOG_NOTICE) << "UDPTracker::sendAnnounce()" << endl;
transaction_id = socket->newTransactionID();
/*
0 64-bit integer connection_id
--- trunk/extragear/network/ktorrent/libktorrent/torrent/udptracker.h #582526:582527
@@ -62,7 +62,7 @@
virtual void completed();
virtual void manualUpdate();
virtual Uint32 failureCount() const {return n;}
-
+ virtual void scrape();
private slots:
void onConnTimeout();
--- trunk/extragear/network/ktorrent/libktorrent/util/sha1hash.cpp #582526:582527
@@ -85,6 +85,13 @@
hash[15],hash[16],hash[17],hash[18],hash[19]);
return QString(tmp);
}
+
+ QByteArray SHA1Hash::toByteArray() const
+ {
+ QByteArray arr(20);
+ arr.duplicate((const char*)hash,20);
+ return arr;
+ }
QString SHA1Hash::toURLString() const
{
--- trunk/extragear/network/ktorrent/libktorrent/util/sha1hash.h #582526:582527
@@ -20,6 +20,7 @@
#ifndef BTSHA1HASH_H
#define BTSHA1HASH_H
+#include <qcstring.h>
#include "constants.h"
class QString;
@@ -136,6 +137,10 @@
*/
friend bool operator < (const SHA1Hash & a,const SHA1Hash & b);
+ /**
+ * Convert the hash to a byte array.
+ */
+ QByteArray toByteArray() const;
};
}
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpmcastsocket.cpp #582526:582527
@@ -153,7 +153,7 @@
}
if (!validDevice)
{
- Out(SYS_PNP|LOG_IMPORTANT) << "Not a valid Internet Gateway Device" << endl;
+ // Out(SYS_PNP|LOG_IMPORTANT) << "Not a valid Internet Gateway Device" << endl;
return 0;
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic