[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